package com.huawang.mdesign.model.service.inter;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.huawang.business.constants.ErrorCode;
import com.huawang.business.constants.ItemTypeEnum;
import com.huawang.business.dto.*;
import com.huawang.business.dto.graph.ModelInfo;
import com.huawang.business.dto.project.Project;
import com.huawang.business.dto.property.ActiveHyperLinkInfo;
import com.huawang.business.dto.property.Link;
import com.huawang.business.dto.property.RelatedProperty;
import com.huawang.business.dto.property.RelatedPropertyConfig;
import com.huawang.business.entity.matrix.CustomListHolder;
import com.huawang.business.entity.ownedproperty.QueryOwnedPropertyForm;
import com.huawang.business.entity.share.ShareHangLocation;
import com.huawang.business.exception.AbortExecutionException;
import com.huawang.business.exception.DisplayForm;
import com.huawang.business.service.customization.ICustomizationService;
import com.huawang.business.service.encapsulation.EncapsulationService;
import com.huawang.business.service.encapsulation.IEncapsulationService;
import com.huawang.business.service.init.IInitializeService;
import com.huawang.business.service.judge.BusinessJudgeService;
import com.huawang.business.service.model.IQueryModelService;
import com.huawang.business.service.model.base.*;
import com.huawang.business.service.model.core.*;
import com.huawang.business.service.model.core.add.IModelOperation;
import com.huawang.business.service.model.core.delete.DeleteService;
import com.huawang.business.service.model.core.display.ElementShow;
import com.huawang.business.service.model.core.display.ExecutorManager;
import com.huawang.business.service.model.core.display.KeywordsCache;
import com.huawang.business.service.model.core.display.ShowElementManager;
import com.huawang.business.service.model.core.number.GlobalNumberCache;
import com.huawang.business.service.model.core.number.GlobalNumberGenerator;
import com.huawang.business.service.model.core.project.ProjectManager;
import com.huawang.business.service.model.core.property.PropertyManager;
import com.huawang.business.service.model.core.property.PropertyOperations;
import com.huawang.business.service.model.core.property.PropertyQueryParameter;
import com.huawang.business.service.model.core.property.UpdateModelFactory;
import com.huawang.business.service.model.core.property.update.UpdatePropertyFactory;
import com.huawang.business.service.model.core.property.valid.ValidPropertyValueFactory;
import com.huawang.business.service.modelusage.IModelUsageService;
import com.huawang.business.service.navigation.INavigationService;
import com.huawang.business.service.transaction.TransactionServiceImpl;
import com.huawang.business.util.InstanceVoUtils;
import com.huawang.business.vo.*;
import com.huawang.business.vo.display.ConstraintAttr;
import com.huawang.business.vo.display.ElementAttr;
import com.huawang.business.vo.display.ShowAttribute;
import com.huawang.core.definition.mof.UMLDefinitionConstants;
import com.huawang.core.definition.mof.cmof.reflection.impl.BasicRElement;
import com.huawang.core.definition.mof.instances.MetaClassInstance;
import com.huawang.core.definition.query.IQueryDefinitionService;
import com.huawang.core.mof.persistence.constants.LogCodeConstants;
import com.huawang.core.mof.persistence.dao.dos.ExternalDataMappingDO;
import com.huawang.core.mof.persistence.service.datamaping.IQueryExternalDataMappingAccess;
import com.huawang.core.semantics.constants.ModelCreatorType;
import com.huawang.core.semantics.constants.TypeEnum;
import com.huawang.core.semantics.constants.UnVisibleStatus;
import com.huawang.core.semantics.entity.MapOperation;
import com.huawang.core.semantics.entity.MofPropertyInfo;
import com.huawang.core.semantics.entity.queryResult.ExternalMappingDataConverter;
import com.huawang.core.semantics.entity.queryResult.ExternalMappingDataInfo;
import com.huawang.core.semantics.entity.queryResult.MofResultContainer;
import com.huawang.core.semantics.entity.queryResult.QueryPropertyForm;
import com.huawang.core.semantics.entity.script.ElementType;
import com.huawang.core.semantics.entity.transaction.LocalTransaction;
import com.huawang.core.semantics.exception.LocalTransactionNotStartException;
import com.huawang.core.semantics.exception.TransactionNotExistingException;
import com.huawang.core.semantics.service.query.IJudgeService;
import com.huawang.core.semantics.service.save.ISaveExternalDataMappingService;
import com.huawang.mdesign.model.service.config.UAFModelManagerConfig;
import com.huawang.mdesign.model.service.constant.*;
import com.huawang.mdesign.model.service.constant.layout.enums.ShapeTypeEnum;
import com.huawang.mdesign.model.service.dto.*;
import com.huawang.mdesign.model.service.dto.nameRule.NamingRuleInfo;
import com.huawang.mdesign.model.service.dto.propertymerge.*;
import com.huawang.mdesign.model.service.inter.override.UAFPropertyManager;
import com.huawang.mdesign.model.service.request.propertymerge.RealPreviewValue;
import com.huawang.mdesign.model.service.util.LogUtil;
import com.huawang.mdesign.model.service.util.ModelInstanceUtil;
import com.huawang.mdesign.model.service.util.RSAUtils;
import com.huawang.mdesign.model.service.util.SelectElementItemUtil;
import com.huawang.mdesign.model.service.vo.*;
import com.huawang.mdesign.model.service.vo.selectelementitem.SelectAffectElementItem;
import com.huawang.mdesign.model.service.vo.selectelementitem.SelectAffectValueItem;
import com.huawang.mdesign.model.service.vo.selectelementitem.SelectElementItem;
import com.huawang.mdesign.model.service.facade.PropertyConfigService;
import com.huawang.mdesign.model.service.facade.dto.PropertyValue;
import com.huawang.mdesign.model.service.facade.dto.TableColumnInfo;
import com.huawang.mdesign.model.service.inter.related.ExtraPropertyFactory;
import com.huawang.mdesign.model.service.inter.related.IExtraProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.io.IOException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.huawang.business.constants.ModelActionName.*;
import static com.huawang.business.constants.ModelConstantURI.DERIVED_PROPERTY_SPECIFICATION;

@Service
@Primary
@Slf4j
public class ModelService {

    private static final InstanceVo NOT_EXIST_INSTANCE;

    static {
        NOT_EXIST_INSTANCE = new InstanceVo();
        NOT_EXIST_INSTANCE.setId(null);
    }

    @Autowired
    private UmlService umlService;

    @Autowired
    private UAFModelManagerConfig managerConfig;

    @Autowired
    private ProjectManager projectManager;

    @Autowired
    private UAFPropertyManager propertyManager;

    @Autowired
    private PropertyService propertyService;
    @Autowired
    private InternalUmlService internalUmlService;

    @Autowired
    private InternalSpecificationService internalSpecificationService;

    @Autowired
    private RelationshipService relationshipService;
    @Autowired
    private InformationFlowService informationFlowService;
    @Autowired
    @Lazy
    private ShowElementManager showElementManager;

    @Autowired
    private InternalModelIconService internalModelIconService;

    @Autowired
    private ElementShow elementShow;

    @Autowired
    private InternalPropertyService internalPropertyService;

    @Autowired
    private ModelPropertyInfoService modelPropertyInfoService;

    @Autowired
    private ICustomizationService customizationService;

    @Autowired
    private InternalDiagramService internalDiagramService;

    @Autowired
    private ExecutorManager executorManager;

    @Autowired
    private PasteSupplement pasteSupplement;

    @Autowired
    private IEncapsulationService encapsulationService;

    @Autowired
    private DeleteService deleteService;

    @Autowired
    private ElementNameService elementNameService;

    @Autowired
    private TransactionServiceImpl transactionService;

    @Autowired
    private ElementDefineService elementDefineService;

    @Autowired
    private InternalOwnerService internalOwnerService;

    @Resource
    private IQueryModelService iQueryModelService;

    @Autowired
    private UMLFacility umlFacility;

    @Autowired
    private IModelUsageService modelUsageService;

    @Autowired
    private ElementPropertyService elementPropertyService;

    @Autowired
    private IInitializeService initializeService;

    @Autowired
    private ElementFindService elementFindService;

    @Autowired
    private ElementCheckService elementCheckService;

    @Autowired
    private ElementModelInfoService elementModelInfoService;

    @Autowired
    private PropertyOperations operations;

    @Autowired
    private ElementStateService elementStateService;

    @Autowired
    private INavigationService navigationService;

    @Autowired
    private ISaveExternalDataMappingService saveExternalDataMappingService;

    @Autowired
    private IQueryExternalDataMappingAccess queryExternalDataMappingAccess;


    private static final Set<String> PROPERTY_MERGE_NEED_COMPUTED_PROPERTIES = Stream.of(
            UMLDefinitionConstants.NamedElement_satisfies,
            UMLDefinitionConstants.NamedElement_refines,
            UMLDefinitionConstants.NamedElement_verifies,
            UMLDefinitionConstants.NamedElement_allocatedTo,
            UMLDefinitionConstants.NamedElement_allocatedFrom,
            UMLDefinitionConstants.NamedElement_tracedFrom,
            UMLDefinitionConstants.SysML_AbstractRequirement_derived,
            UMLDefinitionConstants.SysML_AbstractRequirement_derivedFrom,
            UMLDefinitionConstants.SysML_AbstractRequirement_satisfiedBy,
            UMLDefinitionConstants.SysML_AbstractRequirement_refinedBy,
            UMLDefinitionConstants.SysML_AbstractRequirement_verifiedBy,
            UMLDefinitionConstants.SysML_AbstractRequirement_tracedTo,
            UMLDefinitionConstants.SysML_AbstractRequirement_master

    ).collect(Collectors.toSet());


    @NotNull
    public MetaClassInstance createModel(AddModelDTO addModelDto, IModelOperation modelOperation) {
        String projectId = addModelDto.getProjectId();
        addModelDto.setParentId(addModelDto.getParentId());
        MetaClassInstance instance = Objects.isNull(modelOperation) ? umlService.addModel(addModelDto) : modelOperation.doHandler(addModelDto);
        afterHandler(instance, addModelDto, modelOperation, false);

        Optional.of(UMLDefinitionConstants.UMLDiagram)
                .filter(e -> internalUmlService.checkInstanceType(projectId, instance, e))
                .map(e -> UMLDefinitionConstants.NamedElement_name)
                .map(e -> internalUmlService.queryStringProperty(projectId, instance, e))
                .filter(StringUtils::isEmpty)
                .map(e -> UMLDefinitionConstants.NamedElement_namespace)
                .map(e -> internalUmlService.queryInstanceProperty(projectId, instance, e))
                .ifPresent(e -> {
                    String name = internalUmlService.queryStringProperty(projectId, e, UMLDefinitionConstants.NamedElement_name);
                    umlService.updateModel(projectId, instance.getId(), UMLDefinitionConstants.NamedElement_name,
                            elementNameService.fetchDefaultName(projectId, name, e, instance));
                });
        return instance;
    }

    @Autowired
    private ValidPropertyValueFactory validPropertyValueFactory;

    @Autowired
    private UpdatePropertyFactory updatePropertyFactory;

    @Autowired
    private IJudgeService iJudgeService;

    @Autowired
    private GlobalNumberCache globalNumberCache;

    @Autowired
    private GlobalNumberGenerator globalNumberGenerator;

    @Autowired
    private IQueryDefinitionService iQueryDefinitionService;

    @Autowired
    private BusinessJudgeService businessJudgeService;

    @Autowired
    private ModelManagerConfig modelManagerConfig;

    @Autowired
    private ExtraPropertyFactory extraPropertyFactory;

    /**
     * 新增模型
     *
     * @param addModelDto
     * @return
     */
    @NotNull
    public ModelResultVo addModel(final AddModelDTO addModelDto) {
        LogUtil.printSerializeOnlineLogs("addModelDto: ", addModelDto);
        final IModelOperation modelOperation = umlService.fetchModelOperation(addModelDto.getMetaclass(),
                addModelDto.getOperation());
        final String projectId = addModelDto.getProjectId();
        final Project project = projectManager.getProject(projectId);
        if (Objects.isNull(project)) {
            throw AbortExecutionException.build(ErrorCode.PROJECT_NOT_FOUND);
        }

        ModelResultVo modelResultVo = new ModelResultVo();

        LocalTransaction transaction = transactionService.createTransaction(projectId, ADD_MODEL);
        try {
            MetaClassInstance result = addModel(addModelDto, modelOperation);
            transactionService.commit(projectId);
            modelResultVo.setInstanceId(result.getId());
            InstanceVoUtils.fillAddModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.ADD_MODEL_ERROR, e);
        }

        return modelResultVo;
    }

    @NotNull
    public MetaClassInstance addModel(AddModelDTO addModelDto, IModelOperation modelOperation) {
        return addModel(addModelDto, modelOperation, Boolean.TRUE);
    }

    @NotNull
    public MetaClassInstance addModel(AddModelDTO addModelDto, IModelOperation modelOperation, boolean isSetNumber) {
        LogUtil.printSerializeOnlineLogs("addModelDto: {}, modelOperation: {}", addModelDto, modelOperation);
        final String projectId = addModelDto.getProjectId();
        addModelDto.setParentId(internalOwnerService.queryValidParent(addModelDto, projectId));
        MetaClassInstance result;
        if (modelOperation == null) {
            result = umlService.addModel(addModelDto);
        } else {
            result = modelOperation.doHandler(addModelDto);
        }

        afterHandler(result, addModelDto, modelOperation, isSetNumber);
        if (internalUmlService.checkInstanceType(projectId, result, UMLDefinitionConstants.UMLDiagram)) {
            final String diagramName = internalUmlService.queryStringProperty(projectId, result,
                    UMLDefinitionConstants.NamedElement_name);
            if (StringUtils.isEmpty(diagramName)) {
                final MetaClassInstance namespace = internalUmlService.queryInstanceProperty(projectId, result,
                        UMLDefinitionConstants.NamedElement_namespace);
                if (Objects.nonNull(namespace)) {
                    final String name = internalUmlService.queryStringProperty(projectId, namespace,
                            UMLDefinitionConstants.NamedElement_name);
                    final String newName = elementNameService.fetchDefaultName(projectId, name, namespace, result);
                    umlService.updateModel(projectId, result.getId(), UMLDefinitionConstants.NamedElement_name, newName);
                }
            }
        }
        return result;
    }

    //新增模型后置处理
    private void afterHandler(MetaClassInstance instance, AddModelDTO addModelDto, IModelOperation modelOperation, boolean isSetNumber) {
        LogUtil.printSerializeOnlineLogs("instance: {}, addModelDto: {}, modelOperation: {}", instance, addModelDto,
                modelOperation);
        final String projectId = addModelDto.getProjectId();
        if (modelOperation != null) {
            modelOperation.afterHandler(instance, addModelDto);
        } else {
            IModelOperation operation = null;
            if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.Behavior)) {
                operation = umlService.fetchModelOperation(UMLDefinitionConstants.Behavior, null);
            }

            if (operation != null) {
                operation.afterHandler(instance, addModelDto);
            }
        }
        if (isSetNumber) {
            // 创建的模型编号
            globalNumberGenerator.createElementSetNumber(projectId, instance);
        }
    }


    /**
     * 根据实例设置默认值
     *
     * @param instanceId 模型id
     * @param projectId  项目id
     * @return ModelResultVo
     */
    @NotNull
    public ModelResultVo saveDefaultValue(final String instanceId, final String projectId) {
        LogUtil.printOnlineLogs("saveDefaultValue -> projectId: {}, instanceId: {}", projectId, instanceId);
        ModelResultVo modelResultVo = new ModelResultVo();

        LocalTransaction transaction = transactionService.createTransaction(projectId, SAVE_DEFAULT_VALUE);
        final MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        final List<MetaClassInstance> slots = internalUmlService.queryListInstanceProperty(projectId, instance,
                UMLDefinitionConstants.InstanceSpecification_slot);
        if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.InstanceSpecification)) {
            try {
                QueryPropertyForm queryPropertyForm = internalUmlService.getQueryPropertyForm(slots,
                        Stream.of(UMLDefinitionConstants.Slot_definingFeature, UMLDefinitionConstants.Slot_value).collect(Collectors.toList()));
                MofResultContainer mofResultContainer = internalUmlService.queryProperty(projectId, queryPropertyForm);
                List<UpdateModelDTO> updateModelDTOS = new ArrayList<>();
                slots.forEach(it -> {
                    final MetaClassInstance property = mofResultContainer.queryInstanceProperty(it.getId(),
                            UMLDefinitionConstants.Slot_definingFeature);
                    if (Objects.nonNull(property)
                            && internalUmlService.checkInstanceType(projectId, property, UMLDefinitionConstants.Property)) {
                        final List<MetaClassInstance> values = mofResultContainer.queryListInstanceProperty(it.getId(),
                                UMLDefinitionConstants.Slot_value);
                        updateModelDTOS.add(UpdateModelFactory.newInstance(projectId, property.getId(), UMLDefinitionConstants.Property_defaultValue,
                                values.get(0)));
                    }
                });
                umlService.updateModelByBatch(updateModelDTOS);
                transactionService.commit(projectId);
                InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
            } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
                throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
            } catch (Exception e) {
                transactionService.rollBack(projectId, transaction);
                throw AbortExecutionException.build(ErrorCode.SERVICE_ERROR, e);
            }

        }
        return modelResultVo;
    }

    /**
     * 查询模型信息
     *
     * @param instanceId
     * @return
     */
    @Nullable
    public InstanceVo query(@NotNull final String projectId,
                            @NotNull final String instanceId) {
        LogUtil.printOnlineLogs("query -> projectId: {}, instanceId: {}", projectId, instanceId);
        List<InstanceVo> instanceVos = queryByIds(projectId, Stream.of(instanceId).collect(Collectors.toList()));
        if (CollectionUtils.isEmpty(instanceVos)) {
            return null;
        }

        return instanceVos.get(0);
    }

    @NotNull
    public InstanceVo makeInstanceVo(final String projectId,
                                     final ModelPropertyInfo model) {
        LogUtil.printSerializeOnlineLogs("makeInstanceVo -> projectId: {}, model: {}", projectId, model);
        MetaClassInstance classInstance = model.getInstance();
        final InstanceVo instanceVo = new InstanceVo();
        instanceVo.setFrom(classInstance.getModelCreatorType().getCreator());
        try {
            instanceVo.setName(queryInstanceName(projectId, model));
            instanceVo.setId(classInstance.getId());
            instanceVo.setMetaClass(classInstance.getClassifier().getName());
            instanceVo.setIsRelationShip(model.getIsRelationShip());
            instanceVo.setOwnerId(queryInstanceOwner(model, instanceVo));
            final List<MetaClassInstance> stereotypes = model.queryListInstanceValue(UMLDefinitionConstants.Element_appliedStereotype);
            instanceVo.setAppliedStereotypes(stereotypes.stream().map(BasicRElement::getId).collect(Collectors.toList()));
            instanceVo.setBaseStereotype(model.getBaseStereotype());

            final ModelInfo info = model.getModelInfo();
            if (info != null) {
                instanceVo.setModelTypeCnName(info.getCnName());
                instanceVo.setModelTypeEnName(info.getEnName());
            }

            instanceVo.setIcon(model.getIcon());
            Set<String> dependentIds = new HashSet<>();
            instanceVo.setShowAttribute(getShowAttribute(projectId, model, dependentIds));
            instanceVo.setDependentIds(dependentIds);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return instanceVo;
    }

    @Nullable
    private String queryInstanceOwner(ModelPropertyInfo model, InstanceVo instanceVo) {
        LogUtil.printSerializeOnlineLogs("model: {}, instanceVo: {}", model, instanceVo);
        MetaClassInstance owner = model.queryInstanceValue(UMLDefinitionConstants.Element_owner);
        if (owner == null) {
            log.warn(String.format("owner不存在, name:%s, metaclass:%s, id:%s", instanceVo.getName(),
                    instanceVo.getMetaClass(),
                    instanceVo.getId()));
            return null;
        }

        return owner.getId();
    }

    @Nullable
    private String queryInstanceName(String projectId, ModelPropertyInfo model) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, model: {}", projectId, model);
        String name;
        if (model.checkInstanceType(UMLDefinitionConstants.ConnectorEnd)) {
            MetaClassInstance roleInstance = model.queryInstanceValue(UMLDefinitionConstants.ConnectorEnd_role);
            if (roleInstance == null) {
                return null;
            }
            name = internalUmlService.queryStringProperty(projectId, roleInstance,
                    UMLDefinitionConstants.NamedElement_name);
        } else if (model.checkInstanceType(UMLDefinitionConstants.Comment)) {
            name = model.queryStringValue(UMLDefinitionConstants.Comment_body);
        } else {
            name = model.queryStringValue(UMLDefinitionConstants.NamedElement_name);
        }
        return name;
    }

    @NotNull
    private ShowAttribute<ElementAttr> getShowAttribute(String projectId,
                                                        ModelPropertyInfo model,
                                                        Set<String> dependentIds) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, model: {}, dependentIds: {}", projectId, model, dependentIds);
        final List<MetaClassInstance> stereotypes =
                model.queryListInstanceValue(UMLDefinitionConstants.Element_appliedStereotype);
        final MetaClassInstance instance = model.getInstance();
        String type = queryShowAttributeType(model);
        ShowElementInfo showElementInfo = new ShowElementInfo(projectId, instance, type, dependentIds, model);
        ShowAttribute<ElementAttr> showAttribute = showElementManager.showElement(showElementInfo);
        if (BooleanUtils.isTrue(model.getIsRelationShip())) {
            RelationshipVo shipVo = relationshipService.fillRelationElementByModel(projectId, model);
            showAttribute.setSourceName(shipVo.getSourceName());
            showAttribute.setTargetName(shipVo.getTargetName());
            showAttribute.setSourceId(shipVo.getSourceId());
            showAttribute.setTargetId(shipVo.getTargetId());
            showAttribute.setIsDirection(shipVo.getIsDirection());
            dependentIds.add(shipVo.getSourceId());
            dependentIds.add(shipVo.getTargetId());
        }

        if (CollectionUtils.isNotEmpty(stereotypes)) {
            showAttribute.setStereotypes(createStereotypeVoList(projectId, stereotypes));
            dependentIds.addAll(stereotypes.stream()
                    .filter(it -> !BusinessJudgeService.isCreatedBySystem(it) && !BusinessJudgeService.isImportFromProfile(it))
                    .map(BasicRElement::getId).collect(Collectors.toSet()));
        }

        showAttribute.setLocation(model.getIcon());
        List<String> keywords = getKeywords(projectId, model, showAttribute.getStereotypes());
        showAttribute.setKeywords(keywords);

        // 导航/超链接，如果Element-activeHyperLink属性值存在，用其来构造一个FileVo，如果不存在，则为图元快捷跳转，获取模型下的第一张图
        FileVo fileVo = queryFileVo(projectId, model);
        if (fileVo != null) {
            showAttribute.setContainFirstDiagram(fileVo);
            dependentIds.add(fileVo.getInstanceId());
        }

        // 图元显示约束
        List<MetaClassInstance> constraints = model.queryListInstanceValue(UMLDefinitionConstants.Element_constraints);
        if (CollectionUtils.isNotEmpty(constraints)) {
            List<ModelPropertyInfo> constraintModels = modelPropertyInfoService.createModelPropertyInfoList(projectId,
                    constraints, Stream.of(UMLDefinitionConstants.Constraint_specification).collect(Collectors.toList()));
            List<ConstraintAttr> constraintAttrs = constraintModels.stream().map(constraintModel -> {
                final MetaClassInstance constraint = constraintModel.getInstance();
                ShowElementInfo constraintShowElementInfo = new ShowElementInfo(projectId, constraint,
                        constraint.getType().getId(), dependentIds, constraintModel);
                dependentIds.add(constraint.getId());
                ShowAttribute<ElementAttr> constraintShowAttribute = elementShow.showConstraint(constraintShowElementInfo);
                return (ConstraintAttr) constraintShowAttribute.getExtraAttribute();
            }).collect(Collectors.toList());
            showAttribute.setConstraints(constraintAttrs);
        }

        if (showAttribute.getExtraAttribute() == null) {
            showAttribute.setExtraAttribute(new ElementAttr());
        }

        return showAttribute;
    }

    @Nullable
    private FileVo queryFileVo(String projectId, ModelPropertyInfo model) {
        LogUtil.printSerializeOnlineLogs("queryFileVo -> projectId: {}, model: {}", projectId, model);
        String activeHyperLink = model.queryStringValue(UMLDefinitionConstants.Element_activeHyperLink);
        if (Objects.isNull(activeHyperLink) || StringUtils.equals("", activeHyperLink)) {
            FileVo fileVo = getContainFirstDiagram(projectId, model);
            if (StringUtils.isNotEmpty(fileVo.getInstanceId())) {
                return fileVo;
            }

            return null;
        } else {
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                ActiveHyperLinkInfo activeHyperLinkInfo = objectMapper.readValue(activeHyperLink, ActiveHyperLinkInfo.class);
                if (Objects.equals(activeHyperLinkInfo.getIdType(), "ownedDiagramId")
                        || Objects.equals(activeHyperLinkInfo.getIdType(), "typedOwnedDiagramId")) {
                    FileVo fileVo = new FileVo();
                    fileVo.setInstanceId(activeHyperLinkInfo.getActiveId());
                    MetaClassInstance hyperLinkInstance = internalUmlService.fetchInstance(
                            activeHyperLinkInfo.getActiveId(), projectId);
                    fileVo.setFile(internalModelIconService.queryIcon(projectId, hyperLinkInstance));
                    fileVo.setType("MODEL");
                    return fileVo;
                } else {
                    return createFileVoByOtherHyperLink(projectId, activeHyperLinkInfo);

                }


            } catch (IOException e) {
                throw AbortExecutionException.build(ErrorCode.JSON_DATA_PARSE_ERROR, e);
            }

        }

    }

    @Nullable
    private FileVo createFileVoByOtherHyperLink(String projectId, ActiveHyperLinkInfo activeHyperLinkInfo) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, activeHyperLinkInfo: {}", projectId, activeHyperLinkInfo);
        FileVo fileVo = new FileVo();
        List<Link> links = activeHyperLinkInfo.getLinks();
        if (CollectionUtils.isNotEmpty(links)) {
            List<Link> linkList = links.stream().filter(it ->
                    Objects.equals(it.getId(), activeHyperLinkInfo.getActiveId())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(linkList)) {
                final String linkUrl = linkList.get(0).getUrl();
                final String linkType = linkList.get(0).getType();
                fileVo.setInstanceId(linkUrl);
                fileVo.setType(linkType);
                if (StringUtils.equals("MODEL", linkType)) {
                    MetaClassInstance activeInstance = internalUmlService.fetchInstance(linkList.get(0).getUrl(), projectId);
                    fileVo.setFile(internalModelIconService.queryIcon(projectId, activeInstance));
                } else if (StringUtils.equals("URL", linkType)) {
                    fileVo.setFile("statics/icons/attrTip/iconlink.svg");
                } else if (StringUtils.equals("FILE", linkType)) {
                    fileVo.setFile("statics/icons/attrTip/iconfile.svg");
                    if (linkList.get(0).getUrl().endsWith(".jpg")
                            || linkList.get(0).getUrl().endsWith(".png")
                            || linkList.get(0).getUrl().endsWith(".gif")
                            || linkList.get(0).getUrl().endsWith(".svg")) {
                        fileVo.setFile("statics/icons/attrTip/iconpng.svg");
                    }
                } else {
                    log.info("linkUrl:{}的类型:{}不为MODEL、URL或FILE", linkUrl, linkType);
                }
                return fileVo;
            }
        }
        return null;
    }

    @NotNull
    private static String queryShowAttributeType(ModelPropertyInfo model) {
        LogUtil.printSerializeOnlineLogs("model: ", model);
        final List<MetaClassInstance> stereotypes =
                model.queryListInstanceValue(UMLDefinitionConstants.Element_appliedStereotype);
        if (model.checkInstanceType(UMLDefinitionConstants.InstanceSpecification)) {
            return model.getInstance().getType().getId();
        }

        if (CollectionUtils.isEmpty(stereotypes)) {
            return model.getInstance().getType().getId();
        }

        String firstStereotype = model.getBaseStereotype();
        if (StringUtils.isNotEmpty(firstStereotype)) {
            String[] firstStereotypes = firstStereotype.split("::");
            return firstStereotypes[firstStereotypes.length - 1];
        }

        // 判断stereotype是否为系统内置
        if (BusinessJudgeService.isCreatedBySystem(stereotypes.get(0)) || BusinessJudgeService.isImportFromProfile(stereotypes.get(0))) {
            String[] firstStereotypes = stereotypes.get(0).getId().split("::");
            return firstStereotypes[firstStereotypes.length - 1];
        }

        return model.getInstance().getType().getId();
    }

    /**
     * 图元快捷跳转，获取模型下包含的第一张图
     *
     * @param projectId
     * @param model
     * @return com.huawang.mdesign.model.service.vo.FileVo
     * @author baibf
     * @date 2022/06/01 14:51
     */
    @NotNull
    private FileVo getContainFirstDiagram(String projectId, ModelPropertyInfo model) {
        LogUtil.printSerializeOnlineLogs("getContainFirstDiagram -> projectId: {}, model: {}", projectId, model);
        FileVo fileVo = new FileVo();
        List<MetaClassInstance> ownedDiagrams = model.queryListInstanceValue(UMLDefinitionConstants.Namespace_ownedDiagram);
        ModelInfo info;
        if (CollectionUtils.isEmpty(ownedDiagrams)) {
            if (!model.checkInstanceType(UMLDefinitionConstants.BehavioredClassifier) && !model.checkInstanceType(UMLDefinitionConstants.State)) {
                return fileVo;
            }
            final List<MetaClassInstance> ownedElements = new ArrayList<>();
            if (model.checkInstanceType(UMLDefinitionConstants.BehavioredClassifier)) {
                ownedElements.addAll(
                        model.queryListInstanceValue(UMLDefinitionConstants.BehavioredClassifier_ownedBehavior)
                );
            }
            if (model.checkInstanceType(UMLDefinitionConstants.State)) {
                ownedElements.add(model.queryInstanceValue(UMLDefinitionConstants.State_submachine));
            }
            if (CollectionUtils.isEmpty(ownedElements)) {
                return fileVo;
            }
            for (MetaClassInstance element : ownedElements) {
                List<MetaClassInstance> ownedDiagramList = internalUmlService.queryListInstanceProperty(projectId,
                        element, UMLDefinitionConstants.Namespace_ownedDiagram);
                if (CollectionUtils.isNotEmpty(ownedDiagramList)) {
                    info = internalUmlService.fetchModelInfoValue(projectId, ownedDiagramList.get(0));
                    if (Objects.nonNull(info)) {
                        fileVo.setFile(info.getIcon());
                        fileVo.setInstanceId(ownedDiagramList.get(0).getId());
                    }
                    return fileVo;
                }
            }
            return fileVo;
        }
        info = internalUmlService.fetchModelInfoValue(projectId, ownedDiagrams.get(0));
        if (Objects.nonNull(info)) {
            fileVo.setFile(info.getIcon());
            fileVo.setInstanceId(ownedDiagrams.get(0).getId());
        }
        return fileVo;
    }

    /**
     * 获取模型显示关键字
     *
     * @param projectId
     * @param model
     * @param stereotypeVos
     * @return java.util.List<java.lang.String>
     * @author xz
     * @date 2022/05/28 16:42
     */
    @NotNull
    private List<String> getKeywords(String projectId, ModelPropertyInfo model, List<ApplyStereotypeVo> stereotypeVos) {
        LogUtil.printSerializeOnlineLogs("getKeywords -> projectId: {}, model: {}, stereotypeVos: {}", projectId, model,
                stereotypeVos);
        List<String> keywords = getCustomizationKeywords(projectId, model, stereotypeVos);
        if (CollectionUtils.isNotEmpty(keywords)) {
            return keywords;
        }

        if (model.checkInstanceType(UMLDefinitionConstants.SysML_BindingConnector)) {
            keywords = Collections.singletonList("equal");
        } else if (model.checkInstanceType(UMLDefinitionConstants.SysML_ParticipantProperty)) {
            keywords = Collections.singletonList("参与者");
        } else if (model.checkInstanceType(UMLDefinitionConstants.Property)) {
            final List<MetaClassInstance> stereotypes = model.queryListInstanceValue(UMLDefinitionConstants.Element_appliedStereotype)
                    .stream().filter(it ->
                            !it.getId().contains("Property")).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(stereotypes)) {
                keywords = createStereotypeVoList(projectId, stereotypes).stream().map(ApplyStereotypeVo::getCnName)
                        .collect(Collectors.toList());
            } else {
                keywords = Collections.emptyList();
            }

        } else if (model.checkInstanceType(UMLDefinitionConstants.InstanceSpecification)
                && BusinessJudgeService.isCreatedInteractive(model.getInstance())) {
            keywords = getInstanceSpecificationKeyword(projectId, model, stereotypeVos, keywords);

        } else if (model.checkInstanceType(UMLDefinitionConstants.ActivityPartition)) {
            keywords = getKeywordsFromActivityPartition(projectId, model, stereotypeVos);
        } else if (CollectionUtils.isNotEmpty(stereotypeVos)) {
            keywords = getStereotypeKeywords(stereotypeVos);
        } else if (model.checkInstanceType(UMLDefinitionConstants.UseCase)) {
            keywords = Collections.emptyList();
        } else if (model.checkInstanceType(UMLDefinitionConstants.ObjectNode)) {
            MetaClassInstance propertyType = model.queryInstanceValue(UMLDefinitionConstants.TypedElement_type);
            if (propertyType != null) {
                final List<MetaClassInstance> typeStereotypes =
                        model.queryListInstanceValue(UMLDefinitionConstants.Element_appliedStereotype);
                ModelPropertyInfo propertyTypeModel =
                        modelPropertyInfoService.createSimpleModelPropertyInfo(projectId,
                                propertyType,
                                Collections.emptyList());
                keywords = getKeywords(projectId, propertyTypeModel, createStereotypeVoList(projectId, typeStereotypes));
            } else {
                keywords = getClassifierLabel(model);
            }
        } else {
            keywords = getClassifierLabel(model);
        }

        return keywords;
    }

    /**
     * 获取活动区域模型的显示关键字
     *
     * @param projectId
     * @param model
     * @param stereotypeVos
     * @return
     */
    private List<String> getKeywordsFromActivityPartition(String projectId, ModelPropertyInfo model, List<ApplyStereotypeVo> stereotypeVos) {
        List<ApplyStereotypeVo> appliedStereotypes = stereotypeVos.stream().filter(it -> internalUmlService.isHideMetaType(it.getId())).collect(Collectors.toList());
        if (appliedStereotypes.isEmpty()) {
            MetaClassInstance represents = internalUmlService.queryInstanceProperty(projectId, model.getInstance(), UMLDefinitionConstants.ActivityPartition_represents);
            if (represents != null) {
                List<MetaClassInstance> representsAppliedStereotypes = internalUmlService.queryListInstanceProperty(projectId, represents, UMLDefinitionConstants.Element_appliedStereotype);
                if (!representsAppliedStereotypes.isEmpty()) {
                    List<ApplyStereotypeVo> representsApplyStereotypeVos = createStereotypeVoList(projectId, representsAppliedStereotypes);
                    ModelPropertyInfo representsModel =
                            modelPropertyInfoService.createSimpleModelPropertyInfo(projectId,
                                    represents,
                                    Collections.emptyList());
                    return getKeywords(projectId, representsModel, representsApplyStereotypeVos);
                }
            }
        } else {
            return appliedStereotypes.stream().map(ApplyStereotypeVo::getCnName).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    @NotNull
    private List<String> getInstanceSpecificationKeyword(String projectId, ModelPropertyInfo model, List<ApplyStereotypeVo> stereotypeVos, List<String> keywords) {
        LogUtil.printSerializeOnlineLogs("getInstanceSpecificationKeyword -> projectId: {}, model: {}, stereotypeVos: {}",
                projectId, model, stereotypeVos);
        if (stereotypeVos.stream().anyMatch(it -> Objects.equals(it.getId(), UMLDefinitionConstants.Customization_Unit)
                || Objects.equals(it.getId(), UMLDefinitionConstants.Customization_QuantityKind))) {
            keywords = stereotypeVos.stream().map(ApplyStereotypeVo::getCnName).collect(Collectors.toList());
        } else {
            List<MetaClassInstance> appliedStereotypes = model.queryListInstanceValue(UMLDefinitionConstants.Element_appliedStereotype);
            if (CollectionUtils.isEmpty(appliedStereotypes)) {
                List<MetaClassInstance> classifiers = model.queryListInstanceValue(UMLDefinitionConstants.InstanceSpecification_classifier);
                if (CollectionUtils.isNotEmpty(classifiers)) {
                    final List<MetaClassInstance> stereotypes =
                            model.queryListInstanceValue(UMLDefinitionConstants.Element_appliedStereotype);
                    keywords = getStereotypeKeywords(createStereotypeVoList(projectId, stereotypes));
                }
            } else {
                keywords = getStereotypeKeywords(createStereotypeVoList(projectId, appliedStereotypes));
            }
        }
        return keywords;
    }

    @NotNull
    private List<String> getStereotypeKeywords(List<ApplyStereotypeVo> stereotypeVos) {
        LogUtil.printSerializeOnlineLogs("stereotypeVos: ", stereotypeVos);
        return stereotypeVos.stream().filter(it -> internalUmlService.isHideMetaType(it.getId()))
                .map(ApplyStereotypeVo::getCnName).collect(Collectors.toList());
    }

    @NotNull
    private List<String> getClassifierLabel(ModelPropertyInfo model) {
        LogUtil.printSerializeOnlineLogs("model: {}", model);
        List<String> keywords;
        ModelInfo info = managerConfig.getModelInfoConfig().get(model.getInstance().getClassifier().getId());
        if (info != null) {
            // 活动图中部分Action的keyword与name是不一致的，所以使用Label
            keywords = Collections.singletonList(info.getLabel());
        } else {
            keywords = Collections.emptyList();
        }

        return keywords;
    }

    @NotNull
    private List<ApplyStereotypeVo> createStereotypeVoList(String projectId, List<MetaClassInstance> stereotypes) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, stereotypes: {}", projectId, stereotypes);
        return stereotypes.stream().map(it -> {
            ApplyStereotypeVo applyStereotypeVo = new ApplyStereotypeVo();
            applyStereotypeVo.setId(it.getId());
            ModelInfo info = internalUmlService.fetchStereotypeModelInfo(it.getId());
            if (info != null) {
                applyStereotypeVo.setEnName(info.getEnName());
                applyStereotypeVo.setCnName(info.getCnName());
            } else {
                String name = internalUmlService.queryStringProperty(projectId, it, UMLDefinitionConstants.NamedElement_name);
                applyStereotypeVo.setEnName(name);
                applyStereotypeVo.setCnName(name);
            }

            return applyStereotypeVo;
        }).collect(Collectors.toList());
    }

    /**
     * 批量查询模型信息
     */
    @NotNull
    public List<InstanceVo> queryByIds(@NotNull final String projectId,
                                       @NotNull List<String> instanceIds) {
        LogUtil.printOnlineLogs("projectId: {}, stereotypes: {}", projectId, instanceIds);
        final List<MetaClassInstance> metaClassInstances = this.internalUmlService.fetchInstanceByIds(instanceIds, projectId);
        log.warn("查询到了{}个模型！", metaClassInstances.size());
        List<InstanceVo> instanceVos = this.executorManager.executes(
                projectId,
                metaClassInstances,
                proceedingComputedStatuses ->
                        this.executorManager.getMakeInstanceVo(projectId, proceedingComputedStatuses),
                InstanceVo.class);

        log.warn("编号信息后置处理！");
        numberInfoPostProcessor(projectId, metaClassInstances, instanceVos);
        log.warn("queryByIds结果！总{}个模型", instanceVos.size());
        log.warn("属性查询后置处理！");
        return instanceVos;
    }

    /**
     * 编号信息后置处理
     *
     * @param projectId
     * @param metaClassInstances
     * @param instanceVos
     * @return void
     * @author baibf
     * @date 2024/10/21 11:10
     */
    private void numberInfoPostProcessor(@NotNull String projectId, List<MetaClassInstance> metaClassInstances, List<InstanceVo> instanceVos) {
        log.warn("开始查询元素自动编号属性Map！");
        Map<String, MetaClassInstance> elementAutoNumberPropertyMap = queryElementAutoNumberPropertyMap(projectId, metaClassInstances);
        Set<String> propertyIds = elementAutoNumberPropertyMap.values().stream().map(BasicRElement::getId).collect(Collectors.toSet());
        log.warn("编号属性: {}", propertyIds);
        QueryPropertyForm queryPropertyForm = internalUmlService.getQueryPropertyForm(metaClassInstances, new ArrayList<>(propertyIds));
        MofResultContainer instanceResult = internalUmlService.queryProperty(projectId, queryPropertyForm);
        instanceVos.forEach(instanceVo -> {
            String instanceId = instanceVo.getId();
            MetaClassInstance autoNumberProperty = elementAutoNumberPropertyMap.get(instanceId);
            if (Objects.nonNull(autoNumberProperty)) {
                String autoNumberPropertyId = autoNumberProperty.getId();
                NumberInfo numberInfo = new NumberInfo();
                numberInfo.setNumberPropertyKey(autoNumberPropertyId);
                numberInfo.setNumber(instanceResult.queryStringProperty(instanceId, autoNumberPropertyId));
                instanceVo.getShowAttribute().setNumberInfo(numberInfo);
            }
        });
    }

    @Autowired
    private PropertyGroupService propertyGroupService;


    public Map<String, MetaClassInstance> queryElementAutoNumberPropertyMap(String projectId,
                                                                            List<MetaClassInstance> instances) {
        QueryPropertyForm instanceStereotypeForm = internalUmlService.getQueryPropertyForm(instances,
                Stream.of(UMLDefinitionConstants.Element_appliedStereotype).collect(Collectors.toList()));
        MofResultContainer stereotypeResult = internalUmlService.queryProperty(projectId, instanceStereotypeForm);
        // 查询当前模型自定义的构造型
        log.warn("查询当前模型自定义的构造型!!!");
        Map<String, List<MetaClassInstance>> customizationAppliedStereotypeMap = globalNumberCache.queryCustomizationAppliedStereotypesMapByInstances(projectId, instances);

        Map<String, MetaClassInstance> elementAutoNumberPropertyMap = new HashMap<>();
        // 查模型的stereotype
        Set<String> allStereotypeIds = instances.stream().flatMap(instance -> {
            List<MetaClassInstance> stereotypeList = new ArrayList<>(stereotypeResult.queryListInstanceProperty(instance.getId(),
                    UMLDefinitionConstants.Element_appliedStereotype));
            List<MetaClassInstance> customizationAppliedStereotypes = customizationAppliedStereotypeMap.get(instance.getId());
            if (CollectionUtils.isNotEmpty(customizationAppliedStereotypes)) {
                stereotypeList.addAll(customizationAppliedStereotypes);
            }
            return stereotypeList.stream().map(MetaClassInstance::getId);
        }).collect(Collectors.toSet());
        log.warn("查到模型的stereotype：{}", allStereotypeIds);
        Map<String, List<String>> stereotypePropertiesMap = new HashMap<>();
        // 查stereotype属性
        allStereotypeIds.forEach(stereotypeId ->
                stereotypePropertiesMap.put(stereotypeId, internalUmlService.queryStereotypeProperties(projectId, stereotypeId))
        );
        List<String> allStereotypePropertyIds = stereotypePropertiesMap.values().stream().flatMap(Collection::stream).distinct()
                .collect(Collectors.toList());
        log.warn("查到stereotype的属性：{}", allStereotypePropertyIds);
        // 通过stereotype属性反向查AutoNumber
        Map<String, List<MetaClassInstance>> numberedPropertyAutoNumberMap = internalUmlService.queryPropertyRelationInstanceMap(
                projectId, UMLDefinitionConstants.Customization_AutoNumber_numberedProperty, allStereotypePropertyIds);
        if (numberedPropertyAutoNumberMap.isEmpty()) {
            return elementAutoNumberPropertyMap;
        }
        elementAutoNumberPropertyMapHandle(projectId, instances, elementAutoNumberPropertyMap, stereotypeResult,
                customizationAppliedStereotypeMap, stereotypePropertiesMap, numberedPropertyAutoNumberMap);
        return elementAutoNumberPropertyMap;
    }

    private void elementAutoNumberPropertyMapHandle(String projectId, List<MetaClassInstance> instances, Map<String, MetaClassInstance> elementAutoNumberPropertyMap,
                                                    MofResultContainer stereotypeResult, Map<String, List<MetaClassInstance>> customizationAppliedStereotypeMap,
                                                    Map<String, List<String>> stereotypePropertiesMap, Map<String, List<MetaClassInstance>> numberedPropertyAutoNumberMap) {

        List<MetaClassInstance> allAutoNumberList = numberedPropertyAutoNumberMap.values().stream().flatMap(Collection::stream)
                .distinct().collect(Collectors.toList());
        log.info("查到了{}个AutoNumber", allAutoNumberList.size());
        QueryPropertyForm autoNumberForm = internalUmlService.getQueryPropertyForm(allAutoNumberList,
                Stream.of(UMLDefinitionConstants.Customization_AutoNumber_numberedProperty,
                        UMLDefinitionConstants.Customization_AutoNumber_defaultNumber).collect(Collectors.toList()));
        MofResultContainer autoNumberResult = internalUmlService.queryProperty(projectId, autoNumberForm);
        for (MetaClassInstance instance : instances) {
            if (elementCheckService.checkInstanceType(projectId, instance, UMLDefinitionConstants.SysML_AbstractRequirement)) {
                MetaClassInstance abstractRequirementId = elementFindService.fetchInstance(UMLDefinitionConstants.SysML_AbstractRequirement_id, projectId);
                elementAutoNumberPropertyMap.put(instance.getId(), abstractRequirementId);
            } else {
                List<MetaClassInstance> stereotypeList = new ArrayList<>(stereotypeResult.queryListInstanceProperty(instance.getId(),
                        UMLDefinitionConstants.Element_appliedStereotype));
                List<MetaClassInstance> customizationAppliedStereotypes = customizationAppliedStereotypeMap.get(instance.getId());
                if (CollectionUtils.isNotEmpty(customizationAppliedStereotypes)) {
                    stereotypeList.addAll(customizationAppliedStereotypes);
                }
                if (CollectionUtils.isEmpty(stereotypeList)) {
                    continue;
                }
                List<String> stereotypePropertyIds = stereotypeList.stream().flatMap(stereotype ->
                        stereotypePropertiesMap.get(stereotype.getId()).stream()).distinct().collect(Collectors.toList());
                if (CollectionUtils.isEmpty(stereotypePropertyIds)) {
                    continue;
                }
                List<MetaClassInstance> autoNumberList = getAutoNumberList(stereotypePropertyIds, numberedPropertyAutoNumberMap);
                if (CollectionUtils.isEmpty(autoNumberList)) {
                    continue;
                }
                if (autoNumberList.size() == 1) {
                    MetaClassInstance autoNumberProperty = autoNumberResult.queryInstanceProperty(autoNumberList.get(0).getId(),
                            UMLDefinitionConstants.Customization_AutoNumber_numberedProperty);
                    elementAutoNumberPropertyMap.put(instance.getId(), autoNumberProperty);
                    continue;
                }
                List<MetaClassInstance> defaultNumberIsFalseAutoNumberList = autoNumberList.stream().filter(autoNumber -> {
                    Boolean defaultNumber = autoNumberResult.queryBooleanProperty(autoNumber.getId(),
                            UMLDefinitionConstants.Customization_AutoNumber_defaultNumber);
                    return BooleanUtils.isFalse(defaultNumber);
                }).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(defaultNumberIsFalseAutoNumberList)) {
                    String lastAutoNumberId = internalUmlService.findLastCreatedElement(autoNumberList);
                    MetaClassInstance autoNumberProperty = autoNumberResult.queryInstanceProperty(lastAutoNumberId,
                            UMLDefinitionConstants.Customization_AutoNumber_numberedProperty);
                    elementAutoNumberPropertyMap.put(instance.getId(), autoNumberProperty);
                    continue;
                }
                String lastAutoNumberId = internalUmlService.findLastCreatedElement(defaultNumberIsFalseAutoNumberList);
                log.warn("最后一个AutoNumber的模型Id: {}", lastAutoNumberId);
                MetaClassInstance autoNumberProperty = autoNumberResult.queryInstanceProperty(lastAutoNumberId,
                        UMLDefinitionConstants.Customization_AutoNumber_numberedProperty);
                elementAutoNumberPropertyMap.put(instance.getId(), autoNumberProperty);
            }
        }
    }

    private List<MetaClassInstance> getAutoNumberList(List<String> stereotypePropertyIds, Map<String, List<MetaClassInstance>> numberedPropertyAutoNumberMap) {
        return stereotypePropertyIds.stream().flatMap(stereotypePropertyId -> {
            List<MetaClassInstance> autoNumbers = numberedPropertyAutoNumberMap.get(stereotypePropertyId);
            if (CollectionUtils.isNotEmpty(autoNumbers)) {
                return autoNumbers.stream();
            }
            return null;
        }).filter(Objects::nonNull).distinct().collect(Collectors.toList());
    }


    @NotNull
    public List<String> fetchAllPackages(@NotNull final String projectId, @NotNull final String instanceId) {
        LogUtil.printOnlineLogs("fetchAllPackages -> projectId: {}, instanceId: {}", projectId, instanceId);
        final Project project = projectManager.getProject(projectId);
        if (Objects.isNull(project)) {
            throw AbortExecutionException.build(ErrorCode.PROJECT_NOT_FOUND);
        }

        final MetaClassInstance root = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(root)) {
            log.error("根节点不存在:{}", instanceId);
            throw AbortExecutionException.build(ErrorCode.PARAM_ERROR);
        }
        final Set<String> ids = new HashSet<>();
        ids.add(instanceId);
        ids.addAll(recursionPackages(projectId, root));
        return new ArrayList<>(ids);
    }

    @NotNull
    private List<String> recursionPackages(@NotNull final String projectId,
                                           @NotNull final MetaClassInstance root) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, root: {}", projectId, root);
        final List<MetaClassInstance> allPackages = this.elementFindService
                .querySpecifiedInstanceList(projectId, UMLDefinitionConstants.Package);
        final List<MetaClassInstance> hasSuffixPackages = this.getHasSuffixPackages(projectId, root, allPackages);
        return this.getAllNestedPackages(projectId, root, allPackages, hasSuffixPackages);
    }


    @NotNull
    private ArrayList<String> getAllNestedPackages(@NotNull final String projectId,
                                                   @NotNull final MetaClassInstance root,
                                                   @NotNull final List<MetaClassInstance> allPackages,
                                                   @NotNull final List<MetaClassInstance> hasSuffixPackages) {
        final List<String> rootAncestorIds = this.elementFindService.getAncestorIds(projectId, root, true);
        final Set<String> findPackageIds = new HashSet<>();
        final Set<String> allPackageIds = allPackages.stream()
                .map(BasicRElement::getId)
                .collect(Collectors.toSet());
        for (MetaClassInstance allPackage : hasSuffixPackages) {
            List<String> ancestorIds = this.elementFindService.getAncestorIds(projectId, allPackage, true);
            this.removeSuffix(ancestorIds, rootAncestorIds);
            for (int i = 0; i < ancestorIds.size(); i++) {
                final String ancestorId = ancestorIds.get(i);
                if (findPackageIds.contains(ancestorId)) {
                    findPackageIds.add(allPackage.getId());
                }
                if (!allPackageIds.contains(ancestorId)) {
                    break;
                }
                if (i == (ancestorIds.size() - 1)) {
                    findPackageIds.add(allPackage.getId());
                }
            }
        }
        return new ArrayList<>(findPackageIds);
    }

    /**
     * 获取所有ancestor后缀与root相同的包
     */
    @NotNull
    private List<MetaClassInstance> getHasSuffixPackages(@NotNull final String projectId,
                                                         @NotNull final MetaClassInstance root,
                                                         @NotNull final List<MetaClassInstance> allPackages) {
        final List<String> rootAncestorIds = this.elementFindService.getAncestorIds(projectId, root, true);
        return allPackages.stream()
                .filter(it -> {
                    final List<String> ancestorIds = this.elementFindService.getAncestorIds(projectId, it, true);
                    return this.endWithCommonAncestor(ancestorIds, rootAncestorIds);
                }).collect(Collectors.toList());
    }

    /**
     * target移除source后缀
     */
    private void removeSuffix(@NotNull final List<String> target,
                              @NotNull final List<String> source) {
        int size = source.size();
        for (int i = 0; i < size; i++) {
            if (target.isEmpty()) {
                continue;
            }
            target.remove(target.size() - 1);
        }
    }

    /**
     * targetAncestorIds是否以sourceAncestorIds为后缀
     */
    private boolean endWithCommonAncestor(@NotNull final List<String> targetAncestorIds,
                                          @NotNull final List<String> sourceAncestorIds) {
        for (int i = targetAncestorIds.size() - 1, j = sourceAncestorIds.size() - 1; i >= 0 && j >= 0; i--, j--) {
            final String targetId = targetAncestorIds.get(i);
            final String sourceId = sourceAncestorIds.get(j);
            if (!Objects.equals(targetId, sourceId)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 查询模型到根模型之间的模型，不考虑路径
     *
     * @param instanceIds 模型id列表
     * @return
     */
    @NotNull
    public List<InstanceVo> fetchProfileParentPackages(@NotNull final String projectId,
                                                       @NotNull final List<String> instanceIds) {
        LogUtil.printOnlineLogs("projectId: {}, instanceIds: {}", projectId, instanceIds);
        final Project project = projectManager.getProject(projectId);
        if (Objects.isNull(project)) {
            throw AbortExecutionException.build(ErrorCode.PROJECT_NOT_FOUND);
        }
        final String rootId = project.getRootModel();
        if (StringUtils.isBlank(rootId)) {
            throw AbortExecutionException.build(ErrorCode.PROJECT_ROOT_ERROR);
        }

        final List<MetaClassInstance> instances = this.internalUmlService.fetchInstanceByIds(instanceIds, projectId);
        final Map<MetaClassInstance, List<MetaClassInstance>> ancestorMap =
                this.internalUmlService.getAncestor(projectId, instances);
        final List<MetaClassInstance> ancestors = ancestorMap.values().stream()
                .flatMap(Collection::stream).distinct().collect(Collectors.toList());
        Map<String, ModelPropertyInfo> modelPropertyInfoMap = modelPropertyInfoService.
                makeFullModelPropertyInfo(projectId, new ArrayList<>(ancestors));
        return modelPropertyInfoMap.values().stream().map(it -> makeInstanceVo(projectId, it)).collect(
                Collectors.toList());
    }

    public void initPropertyValue(
            final PropertyConfig config,
            final PropertyValueVo valueVo,
            final String projectId,
            final MetaClassInstance instance) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, instance: {}, config: {}, valueVo: {}", projectId, instance, config,
                valueVo);
        if (Objects.nonNull(valueVo)) {
            // 前端接收枚举必须带个[]
            if (Objects.equals(config.getDataType(), UMLDefinitionConstants.Enumeration) && !(valueVo.getValue() instanceof ArrayList)) {
                config.setValue(Collections.singletonList(valueVo.getValue()));
            } else {
                config.setValue(valueVo.getValue());
            }
            if (StringUtils.isNotBlank(valueVo.getKey())
                    && UMLDefinitionConstants.State_submachine.equals(valueVo.getKey())
                    && BooleanUtils.isTrue(internalUmlService.queryBooleanProperty(projectId, instance,
                    UMLDefinitionConstants.State_isComposite))) {
                config.setReadonly(true);
            }
            if (valueVo.getValueSpecificationInfo() != null) {
                config.setValueSpecificationInfo(valueVo.getValueSpecificationInfo());
            }
        }
    }

    /**
     * 部分场景下readonly需要改变的特殊处理
     *
     * @param projectId
     * @param instance
     * @param infos
     * @return void
     * @author baibf
     * @date 2022/10/20 10:36
     */
    private void setUpReadonly(String projectId, MetaClassInstance instance, List<PropertyConfig> infos) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, instance: {}, infos: {}", projectId, instance, infos);
        Set<String> givenTypes = internalUmlService.getGivenTypes(projectId, instance);
        // 如果是Message，其Signature属性在MessageSort为CreateMessage、DeleteMessage、Reply时为只读
        if (givenTypes.contains(UMLDefinitionConstants.Message)) {
            setMessageReadOnly(projectId, instance, infos);
            return;
        }

        // 时间段约束时创建在给自己消息和递归消息上，其firstEvent属性为只读
        if (givenTypes.contains(UMLDefinitionConstants.DurationConstraint)) {
            PropertyConfig propertyConfig = getPropertyConfigByKey(infos,
                    UMLDefinitionConstants.DurationConstraint_firstEvent);
            if (propertyConfig != null) {
                List<MetaClassInstance> constrainedElements = internalUmlService.queryListInstanceProperty(projectId,
                        instance, UMLDefinitionConstants.Constraint_constrainedElement);
                if (constrainedElements.size() == 1) {
                    propertyConfig.setReadonly(true);
                }
            }

            return;
        }

        if (givenTypes.contains(UMLDefinitionConstants.Simulation_ImageSwitcher)) {
            List<String> keys = Arrays.asList(UMLDefinitionConstants.Simulation_SelectPropertiesConfig_nestedPropertyPaths,
                    UMLDefinitionConstants.Simulation_SelectPropertiesConfig_value,
                    UMLDefinitionConstants.Customization_UI_source);
            List<String> keyList = Collections.singletonList(UMLDefinitionConstants.Element_appliedStereotype);
            updatePropertyConfigByKey(infos, keys, true);
            updatePropertyConfigByKey(infos, keyList, false);
        } else if(givenTypes.contains(UMLDefinitionConstants.TableAndMatrix_PartICDTable)){
            PropertyConfig propertyConfig = getPropertyConfigByKey(infos, UMLDefinitionConstants.TableAndMatrix_DiagramTable_additionalElements);
            if (propertyConfig != null){
                propertyConfig.setReadonly(true);
            }
        } else if(givenTypes.contains(UMLDefinitionConstants.Generalization)){
            PropertyConfig generalPropertyConfig = getPropertyConfigByKey(infos, UMLDefinitionConstants.Generalization_general);
            PropertyConfig specificPropertyConfig = getPropertyConfigByKey(infos, UMLDefinitionConstants.Generalization_specific);
            if (generalPropertyConfig != null && specificPropertyConfig != null){
                generalPropertyConfig.setReadonly(true);
                specificPropertyConfig.setReadonly(true);
            }
        }
    }

    private void setMessageReadOnly(String projectId, MetaClassInstance instance, List<PropertyConfig> infos) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, instance: {}, infos: {}", projectId, instance, infos);
        PropertyConfig propertyConfig = getPropertyConfigByKey(infos,
                UMLDefinitionConstants.Message_messageSort);
        if (propertyConfig != null) {
            Object messageSort = propertyConfig.getValue();
            if (Objects.equals(UMLDefinitionConstants.MessageSort_createMessage, messageSort)
                    || Objects.equals(UMLDefinitionConstants.MessageSort_deleteMessage, messageSort)
                    || Objects.equals(UMLDefinitionConstants.MessageSort_reply, messageSort)) {
                propertyConfig = getPropertyConfigByKey(infos, UMLDefinitionConstants.Message_signature);
                if (propertyConfig != null) {
                    propertyConfig.setReadonly(true);
                }
            } else if (Objects.equals(UMLDefinitionConstants.MessageSort_asynchSignal, messageSort)) {
                final MetaClassInstance kind = internalUmlService.queryInstanceProperty(projectId, instance,
                        UMLDefinitionConstants.Message_messageKind);
                if (Objects.nonNull(kind) && Objects.equals(kind.getId(), UMLDefinitionConstants.MessageKind_lost)) {
                    propertyConfig.setReadonly(true);
                }
            } else {
                log.info("消息的message属性{}不为createMessage、deleteMessage、reply或asynchSignal， 无需特殊处理只读状态", messageSort.toString());
            }
        }
    }


    /**
     * 更新属性配置
     *
     * @param propertyConfigList
     * @return
     */
    private static void updatePropertyConfigByKey(List<PropertyConfig> propertyConfigList,
                                                  List<String> keys,
                                                  boolean updateDisplayLevel) {
        LogUtil.printSerializeOnlineLogs("propertyConfigList: {}, keys: {}, updateDisplayLevel: {}", propertyConfigList, keys,
                updateDisplayLevel);
        if (propertyConfigList != null && keys != null) {
            for (PropertyConfig propertyConfig : propertyConfigList) {
                if (keys.contains(propertyConfig.getKey())) {
                    propertyConfig.setReadonly(true);
                    if (updateDisplayLevel) {
                        propertyConfig.setDisplayLevel(3);
                    }
                }
            }
        }
    }


    /**
     * 根据Key获得属性配置对象
     *
     * @param propertyConfigList
     * @param key
     * @return
     */
    @Nullable
    private static PropertyConfig getPropertyConfigByKey(final List<PropertyConfig> propertyConfigList, final String key) {
        LogUtil.printSerializeOnlineLogs("propertyConfigList: {}, key: {}", propertyConfigList, key);
        if (propertyConfigList != null && key != null) {
            for (PropertyConfig propertyConfig : propertyConfigList) {
                if (key.equals(propertyConfig.getKey())) {
                    return propertyConfig;
                }
            }
        }
        return null;
    }

    /**
     * 查询模型拥有的属性列表
     *
     * @param projectId
     * @param instanceId
     * @return
     */
    @NotNull
    public List<PropertyConfig> queryPropertyListBatch(@NotNull final String projectId,
                                                       @NotNull final String instanceId,
                                                       Integer displayLevel) {
        LogUtil.printOnlineLogs("projectId, instanceId, displayLevel", projectId, instanceId, displayLevel);
        if (projectManager.getProject(projectId) == null) {
            return Collections.emptyList();
        }
        final MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (instance == null) {
            return Collections.emptyList();
        }
        // 根据排序需求，先查找stereotype的attribute，再查找元类的attribute
        List<PropertyConfigDto> configs = queryConfigDtoList(projectId, instance);
        List<PropertyConfig> infos = createPropertyConfigByBatch(projectId, instance, configs, displayLevel);
        // read
        setUpReadonly(projectId, instance, infos);
        //属性信息按照指定名称排序
        propertyFixedOrderSort(infos);
        return infos;
    }

    /**
     * description:查询多个模型的共同属性
     */
    @NotNull
    public List<CommonPropertyVo> queryMultiCommonProperty(QueryMultiCommonPropertyDTO dto) {
        LogUtil.printSerializeOnlineLogs("queryMultiCommonProperty -> dto: ", dto);
        final String projectId = dto.getProjectId();
        final List<String> instanceIds = dto.getInstanceIds();
        if (projectManager.getProject(projectId) == null) {
            log.warn("传入项目id不为空, 但无法查询到对应项目数据");
            return Collections.emptyList();
        }
        final List<MetaClassInstance> instances = internalUmlService.fetchInstanceByIds(instanceIds, projectId);
        if (CollectionUtils.isEmpty(instances)) {
            log.warn("传入模型id组不为空, 但无法查询到对应模型");
            return Collections.emptyList();
        }

        //查询相同属性
        List<PropertyConfigDto> propertyConfigDtos = this.queryInitialProperties(
                projectId, instances);
        //查询属性值
        final Map<MetaClassInstance, List<PropertyConfig>> propertyConfigsMap = queryPropertyListBatchToMap(projectId
                , propertyConfigDtos, instances, dto.getDisplayLevel());
        // 转化批量编辑模型属性的vo数据结构
        Map<String, List<CommonPropertyVo>> commonPropertyConfigMap = propertyConfigsMap.entrySet()
                .stream().flatMap(it -> it.getValue().stream()).map(it -> {
                    CommonPropertyVo commonPropertyVo = new CommonPropertyVo();
                    BeanUtils.copyProperties(it, commonPropertyVo);
                    return commonPropertyVo;
                }).collect(Collectors.groupingBy(PropertyConfig::getKey));
        // 判断属性值是否一致
        List<CommonPropertyVo> result = new ArrayList<>();
        commonPropertyConfigMap.values().forEach(commonPropertyConfigs -> {
            CommonPropertyVo vo = commonPropertyConfigs.get(0);
            if (!areAllElementsEqual(commonPropertyConfigs)) {
                vo.setConsistent(false);
                vo.setValue(null);
            }
            result.add(vo);
        });

        propertyFixedOrderSort(result);
        return result;
    }

    @NotNull
    public List<PropertyConfig> querySyncRulePropertyList(@NotNull final String projectId,
                                                          @NotNull final String instanceId,
                                                          Integer displayLevel) {
        List<PropertyConfig> propertyConfigs = queryPropertyListBatch(projectId, instanceId, displayLevel);
        propertyConfigs.removeIf(it -> {
            // 1.特殊处理过的属性，允许选择
            if (SyncRuleProperty.SPECIAL_HANDLE_PROPERTY.contains(it.getKey())) {
                return false;
            }
            // 2.过滤只读属性
            if (BooleanUtils.isTrue(it.getReadonly())) {
                return true;
            }
            // 3.过滤TypeElement-Type属性，该属性值使用分页查询
            if (StringUtils.equals(it.getKey(), UMLDefinitionConstants.TypedElement_type)) {
                return true;
            }
            // 4.过滤checkValid弹窗树过滤的属性
            String validMethodName = propertyManager.getMethodName(PropertyManager.VALID_PREFIX, it.getKey());
            if (validPropertyValueFactory.query(validMethodName) != null) {
                return true;
            }
            // 5.过滤addValue附带业务逻辑的属性
            PropertyConfig propertyConfig = managerConfig.getPropertyConfigs().get(it.getKey());
            if (propertyConfig != null && Objects.equals(propertyConfig.getItemType(), 2)) {
                return true;
            }
            // 6.过滤updateValue附带业务逻辑的属性
            String updateMethodName = propertyManager.getPropertyMethodName(it.getKey(), PropertyManager.UPDATE_PREFIX, null);
            if (updatePropertyFactory.getOperation(updateMethodName) != null) {
                return true;
            }
            return SyncRuleProperty.FILTER_PROPERTY.contains(it.getKey());
        });
        return propertyConfigs;
    }

    public static boolean areAllElementsEqual(List<CommonPropertyVo> list) {
        LogUtil.printSerializeOnlineLogs("list: ", list);
        Set<Object> uniqueValues = new HashSet<>();
        for (CommonPropertyVo element : list) {
            uniqueValues.add(element.getValue());
            if (uniqueValues.size() > 1) {
                return false;
            }
        }

        return true;
    }

    @NotNull
    private Map<String, Boolean> getReadOnly(String projectId, List<PropertyConfigDto> configDtos) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, configDtos: {}", projectId, configDtos);
        Map<String, Boolean> readOnlyMap = new HashMap<>();
        MofResultContainer container = internalUmlService.queryProperty(projectId,
                internalUmlService.getQueryPropertyForm(internalUmlService.fetchInstanceByIds(configDtos.stream().map(PropertyConfigDto::getKey).collect(Collectors.toList()), projectId),
                        Stream.of(UMLDefinitionConstants.StructuralFeature_isReadOnly).collect(Collectors.toList())));
        configDtos.forEach(configDto -> {
            PropertyConfig config = managerConfig.getPropertyConfigs().get(configDto.getKey());
            if (config != null) {
                readOnlyMap.put(configDto.getKey(), config.getReadonly());
            } else {
                if (configDto.isStereotype()) {
                    readOnlyMap.put(configDto.getKey(), container.queryBooleanProperty(projectId, configDto.getKey()));
                } else {
                    readOnlyMap.put(configDto.getKey(), false);
                }
            }
        });

        return readOnlyMap;
    }

    @NotNull
    private static List<PropertyConfigDto> fetchCommonPropertyConfigDTO(@NotNull List<PropertyConfigDto> propertyConfigListA,
                                                                        @NotNull List<PropertyConfigDto> propertyConfigListB) {
        LogUtil.printSerializeOnlineLogs("propertyConfigListA: {}, propertyConfigListB: {}", propertyConfigListA,
                propertyConfigListB);
        final Map<String, PropertyConfigDto> keyMapA = propertyConfigListA.stream()
                .collect(Collectors.toMap(PropertyConfigDto::getKey, Function.identity(), (k, v) -> k, LinkedHashMap::new));
        final Map<String, PropertyConfigDto> keyMapB = propertyConfigListB.stream()
                .collect(Collectors.toMap(PropertyConfigDto::getKey, Function.identity(), (k, v) -> k, LinkedHashMap::new));
        LinkedHashSet<String> commonKeySet = new LinkedHashSet<>(keyMapA.keySet());
        commonKeySet.retainAll(keyMapB.keySet());
        return commonKeySet.stream().map(keyMapA::get).collect(Collectors.toList());
    }

    @NotNull
    private List<PropertyConfigDto> filterSpecialHandlePropertyInfo(String projectId,
                                                                    @NotNull List<PropertyConfigDto> propertyConfigs) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, propertyConfigs: {}", projectId, propertyConfigs);
        final Map<String, Boolean> readOnlyMap = getReadOnly(projectId, propertyConfigs);
        Set<String> hidePropertiesSet = Stream.of(
                UMLDefinitionConstants.NamedElement_name,
                UMLDefinitionConstants.BehavioredClassifier_interfaceRealization,
                UMLDefinitionConstants.Property_defaultValue,
                UMLDefinitionConstants.Parameter_defaultValue,
                UMLDefinitionConstants.State_stateInvariant,
                UMLDefinitionConstants.MultiplicityElement_lowerValue,
                UMLDefinitionConstants.MultiplicityElement_upperValue,
                UMLDefinitionConstants.TableAndMatrix_DiagramMatrix_relationCriterion,
                UMLDefinitionConstants.TableAndMatrix_DiagramMap_relationCriterion,
                UMLDefinitionConstants.CUSTOMIZATION_DERIVED_EXPRESSION,
                UMLDefinitionConstants.Abstraction_mapping,
                UMLDefinitionConstants.Element_activeHyperLink,
                UMLDefinitionConstants.InstanceSpecification_specification).collect(Collectors.toSet());
        // 1.过滤掉只读元素
        // 2.过滤掉业务上需要隐藏不允许批量修改的HidePropertiesSet
        return propertyConfigs.stream()
                .filter(it -> BooleanUtils.isFalse(readOnlyMap.get(it.getKey())) && !hidePropertiesSet.contains(it.getKey()))
                .collect(Collectors.toList());
    }

    /**
     * description:批量查询模型的属性列表
     */
    @NotNull
    public Map<MetaClassInstance, List<PropertyConfig>> queryPropertyListBatchToMap(@NotNull final String projectId,
                                                                                    List<PropertyConfigDto> commonPropertyConfigs,
                                                                                    @NotNull final List<MetaClassInstance> instances,
                                                                                    Integer displayLevel) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, commonPropertyConfigs: {}, instances: {}, displayLevel: {}", projectId,
                commonPropertyConfigs, instances, displayLevel);
        if (CollectionUtils.isEmpty(instances)) {
            return Collections.emptyMap();
        }

        // 填充模型属性值
        final Map<MetaClassInstance, List<PropertyConfig>> propertyInfosMap = new HashMap<>();
        MofResultContainer container = internalUmlService.queryProperty(projectId,
                internalUmlService.getQueryPropertyForm(instances,
                        commonPropertyConfigs.stream().map(PropertyConfigDto::getKey).collect(Collectors.toList())));
        Map<String, MetaClassInstance> propertyInstanceMap = internalUmlService.fetchInstanceByIds(
                        commonPropertyConfigs.stream().map(PropertyConfigDto::getKey).collect(Collectors.toList()), projectId)
                .stream().collect(Collectors.toMap(BasicRElement::getId, it -> it, (a, b) -> a));
        final List<MetaClassInstance> properties = commonPropertyConfigs.stream()
                .map(it -> propertyInstanceMap.get(it.getKey()))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        final QueryPropertyForm queryPropertyForm = this.internalUmlService
                .getQueryPropertyForm(properties, Stream.of(UMLDefinitionConstants.TypedElement_type,
                        UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.StructuralFeature_isReadOnly).collect(Collectors.toList()));
        final MofResultContainer mofResultContainer = this.internalUmlService.queryProperty(projectId, queryPropertyForm);

        for (MetaClassInstance instance : instances) {
            final String instanceId = instance.getId();
            final List<PropertyConfig> propertyConfigByBatch =
                    this.createPropertyConfigByBatch(projectId, instance, commonPropertyConfigs,
                            container.getMofPropertyInfoMap().get(instanceId), propertyInstanceMap,
                            mofResultContainer,
                            displayLevel);
            propertyInfosMap.put(instance, propertyConfigByBatch);
        }
        propertyInfosMap.keySet().forEach(instance -> {
            List<PropertyConfig> propertyInfos = propertyInfosMap.get(instance);
            setUpReadonly(projectId, instance, propertyInfos);
        });
        return propertyInfosMap;
    }

    @NotNull
    private List<PropertyConfigDto> queryInitialProperties(@NotNull final String projectId,
                                                           @NotNull final List<MetaClassInstance> instances) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, instances: {}", projectId, instances);
        // 批量查询模型自定义属性
        Map<String, List<PropertyConfigDto>> instanceAttributeMap = new HashMap<>(instances.size());
        final QueryOwnedPropertyForm queryOwnedPropertyForm = QueryOwnedPropertyForm.builder()
                .findGeneralCascade(true)
                .findSpecificCascade(false)
                .needOppositeProperty(false)
                .excludeRedefinedProperty(true)
                .excludeReadOnlyProperty(false)
                .excludeComputedProperty(false)
                .isFindStereotypeProperties(true)
                .isFindDerivedProperties(true)
                .isFindCustomizeProperties(true)
                .build();
        final Map<String, List<String>> ownedPropertiesByInstanceIdMap = this.internalUmlService
                .getOwnedPropertiesByInstanceId(projectId, instances, queryOwnedPropertyForm);
        final Map<String, PropertyConfig> propertyConfigs = this.managerConfig.getPropertyConfigs();
        for (MetaClassInstance instance : instances) {
            final String instanceId = instance.getId();
            final List<PropertyConfigDto> propertyConfigDtos = ownedPropertiesByInstanceIdMap
                    .getOrDefault(instanceId, Collections.emptyList()).stream()
                    .filter(propertyConfigs::containsKey)
                    .map(propertyName -> this.getPropertyConfigDto(projectId, propertyName))
                    .collect(Collectors.toList());
            instanceAttributeMap.put(instanceId, propertyConfigDtos);
        }

        List<PropertyConfigDto> propertyConfigDtos = instanceAttributeMap.values().stream()
                .reduce(ModelService::fetchCommonPropertyConfigDTO).orElse(Collections.emptyList());
        propertyConfigDtos = filterSpecialHandlePropertyInfo(projectId, propertyConfigDtos);
        return propertyConfigDtos;
    }

    @NotNull
    private PropertyConfigDto getPropertyConfigDto(@NotNull String projectId, String propertyName) {
        LogUtil.printOnlineLogs("projectId: {}, propertyName: {}", projectId, propertyName);
        boolean isStereotypeProperty = this.internalUmlService.checkIsStereotypeProperty(projectId, propertyName);
        boolean isDerivedProperty = this.internalUmlService.checkIsDerivedProperty(projectId, propertyName);
        final PropertyConfigDto dto = new PropertyConfigDto();
        dto.setType(isDerivedProperty ? DERIVED_PROPERTY_SPECIFICATION : "");
        dto.setKey(propertyName);
        if (isDerivedProperty || isStereotypeProperty) {
            dto.setStereotype(true);
        }
        if (isStereotypeProperty) {
            dto.setStereotype(true);
        }
        return dto;
    }

    @NotNull
    public List<PropertyConfig> queryPropertyListByType(QueryPropertyByTypeDTO dto) {
        LogUtil.printSerializeOnlineLogs("queryPropertyListByType -> dto: ", dto);
        final String projectId = dto.getProjectId();
        List<MetaClassInstance> instances = getMetaclassOrStereotype(dto);
        if (CollectionUtils.isEmpty(instances)) {
            return Collections.emptyList();
        }
        List<String> allPropertyIds = new ArrayList<>();
        instances.forEach(it -> {
            String metaClass = internalUmlService.isOnlyMetaClass(projectId, it) ?
                    it.getId() : internalUmlService.getSelfBasePropertyList(projectId, it).get(0);
            // 查询元类属性
            final QueryOwnedPropertyForm appendModelForm = QueryOwnedPropertyForm.builder()
                    .metaInstanceIds(Collections.singletonList(metaClass))
                    .findGeneralCascade(true)
                    .findSpecificCascade(false)
                    .needOppositeProperty(false)
                    .excludeRedefinedProperty(true)
                    .excludeReadOnlyProperty(true)
                    .excludeComputedProperty(true)
                    .build();
            List<String> metaClassProperties =
                    internalUmlService.getOwnedPropertiesByMetaInstanceIds(projectId, appendModelForm);
            allPropertyIds.addAll(metaClassProperties);

            // 查询构造型属性
            if (!internalUmlService.isOnlyMetaClass(projectId, it)) {
                List<String> stereotypePropertyIds = internalPropertyService.queryStereoProperties(
                        projectId, Collections.singletonList(it));
                allPropertyIds.addAll(stereotypePropertyIds);
            }
        });

        List<MetaClassInstance> allProperties = internalUmlService.fetchInstanceByIds(allPropertyIds, projectId);
        filterSpecialHandleProperty(allProperties);
        final QueryPropertyForm queryPropertyForm = this.internalUmlService
                .getQueryPropertyForm(allProperties, Stream.of(UMLDefinitionConstants.TypedElement_type,
                        UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.StructuralFeature_isReadOnly).collect(Collectors.toList()));
        final MofResultContainer mofResultContainer = this.internalUmlService.queryProperty(projectId, queryPropertyForm);
        List<PropertyConfig> infos = allProperties.stream().map(metaProperty -> {
            PropertyConfigDto propertyConfigDto = new PropertyConfigDto();
            propertyConfigDto.setKey(metaProperty.getId());
            propertyConfigDto.setStereotype(true);
            return initConfig(projectId, metaProperty, propertyConfigDto, instances.get(0), mofResultContainer);
        }).filter(Objects::nonNull).collect(Collectors.toList());
        // read
        instances.forEach(it -> setUpReadonly(projectId, instances.get(0), infos));
        propertyFixedOrderSort(infos);
        return infos;
    }

    /**
     * description:移除一些需要特殊处理的导入属性，不允许用户选择
     */
    private static void filterSpecialHandleProperty(@NotNull List<MetaClassInstance> allProperties) {
        LogUtil.printSerializeOnlineLogs("allProperties: ", allProperties);
        // 1.Namespace_ownedDiagram、ParameterableElement_owningTemplateParameter
        // 2.Element_appliedStereotype:底层限制且已经提供构造型选择的入口,无需通过word数据导入
        Set<String> specialHandlePropertySet = Stream.of(
                        UMLDefinitionConstants.Namespace_ownedDiagram,
                        UMLDefinitionConstants.ParameterableElement_owningTemplateParameter,
                        UMLDefinitionConstants.Element_appliedStereotype)
                .collect(Collectors.toSet());
        allProperties.removeIf(it -> specialHandlePropertySet.contains(it.getId()));
    }

    @NotNull
    public List<MultiPropertyConfigVo> queryMultiPropertyListByType(QueryPropertyByTypeDTO dto) {
        LogUtil.printSerializeOnlineLogs("queryMultiPropertyListByType -> dto: ", dto);
        final String projectId = dto.getProjectId();
        final List<String> metaclassOrStereotype = dto.getMetaclassOrStereotypeList();
        final Boolean needOppositeProperty = dto.getNeedOppositeProperty();
        final Boolean needReadOnlyProperty = dto.getNeedReadOnlyProperty();
        final Boolean needComputedProperty = dto.getNeedComputedProperty();
        if (projectManager.getProject(projectId) == null) {
            log.info("项目文件不存在。");
            return Collections.emptyList();
        }

        final List<MetaClassInstance> instances = internalUmlService.fetchInstanceByIds(metaclassOrStereotype, projectId);
        if (CollectionUtils.isEmpty(instances)) {
            return Collections.emptyList();
        }
        Map<MetaClassInstance, Set<MetaClassInstance>> propertyMap = elementDefineService.queryMetaClassAndBaseClassPropertyListToMap(
                instances, projectId, needOppositeProperty, needReadOnlyProperty, needComputedProperty);
        Map<String, MetaClassInstance> metaClassInstanceMap = propertyMap.keySet().stream().collect(Collectors.toMap(MetaClassInstance::getId, Function.identity(), (v1, v2) -> v1));
        //增加对构造型属性的查询
        List<String> stereotypes = instances.stream().map(MetaClassInstance::getId).filter(e -> iJudgeService.isMetaStereotype(projectId, e)).distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(stereotypes)) {
            List<MetaClassInstance> stereotypeMetaClassInstances = this.internalUmlService.fetchInstanceByIds(new ArrayList<>(stereotypes), projectId);
            for (MetaClassInstance metaClassInstance : stereotypeMetaClassInstances) {
                String stereotypeId = metaClassInstance.getId();
                List<String> stereotypePropertyIds = this.internalUmlService.queryStereotypeProperties(projectId, stereotypeId);
                List<MetaClassInstance> metaClassInstances = internalUmlService.fetchInstanceByIds(stereotypePropertyIds, projectId);
                MetaClassInstance key = metaClassInstanceMap.getOrDefault(metaClassInstance.getId(), metaClassInstance);
                Set<MetaClassInstance> propertiesSet = propertyMap.getOrDefault(key, new HashSet<>());
                propertiesSet.addAll(metaClassInstances);
                propertyMap.putIfAbsent(key, propertiesSet);
            }
        }
        return propertyMap.keySet().stream().map(it -> {
            MultiPropertyConfigVo multiPropertyConfigVo = new MultiPropertyConfigVo();
            String instanceId = it.getId();
            multiPropertyConfigVo.setInstanceId(instanceId);
            multiPropertyConfigVo.setProperties(createPropertyConfigList(projectId, it, propertyMap.get(it)));
            return multiPropertyConfigVo;
        }).collect(Collectors.toList());
    }

    @NotNull
    private List<PropertyConfig> createPropertyConfigList(String projectId,
                                                          MetaClassInstance instance,
                                                          Set<MetaClassInstance> metaProperties) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, instance: {}, metaProperties: {}", projectId, instance,
                metaProperties);
        elementDefineService.removeRefineProperty(projectId, metaProperties);
        final QueryPropertyForm queryPropertyForm = this.internalUmlService
                .getQueryPropertyForm(new ArrayList<>(metaProperties),
                        Stream.of(UMLDefinitionConstants.TypedElement_type, UMLDefinitionConstants.NamedElement_name,
                                UMLDefinitionConstants.StructuralFeature_isReadOnly
                        ).collect(Collectors.toList()));
        final MofResultContainer mofResultContainer = this.internalUmlService.queryProperty(projectId, queryPropertyForm);
        List<PropertyConfig> infos = metaProperties.stream().map(metaProperty -> {
            PropertyConfigDto propertyConfigDto = new PropertyConfigDto();
            propertyConfigDto.setKey(metaProperty.getId());
            propertyConfigDto.setStereotype(true);
            return initConfig(projectId, metaProperty, propertyConfigDto, instance, mofResultContainer);
        }).filter(Objects::nonNull).collect(Collectors.toList());
        setUpReadonly(projectId, instance, infos);
        propertyFixedOrderSort(infos);
        return infos;
    }


    /**
     * 根据属性key查询指定属性值
     *
     * @param configDto
     * @return java.util.List<com.huawang.mdesign.model.service.config.PropertyConfig>
     * @author xz
     * @date 2023/05/23 15:16
     */
    @NotNull
    public List<PropertyConfig> queryPropertyListBatchByKeys(QueryPropertyConfigDTO configDto) {
        LogUtil.printSerializeOnlineLogs("configDto: ", configDto);
        final String projectId = configDto.getProjectId();
        if (CollectionUtils.isEmpty(configDto.getKeys())) {
            return Collections.emptyList();
        }

        final MetaClassInstance instance = internalUmlService.fetchInstance(configDto.getInstanceId(), projectId);
        if (instance == null) {
            return Collections.emptyList();
        }

        List<PropertyConfigDto> configs = configDto.getKeys().stream().map(key -> {
            PropertyConfigDto dto = new PropertyConfigDto();
            dto.setKey(key);
            dto.setStereotype(internalUmlService.checkIsStereotypeProperty(projectId, key));
            return dto;
        }).collect(Collectors.toList());
        // 根据排序需求，先查找stereotype的attribute，再查找元类的attribute
        List<PropertyConfig> infos = createPropertyConfigByBatch(projectId, instance, configs, null);
        propertyFixedOrderSort(infos);
        return infos;
    }

    @NotNull
    public List<PropertyConfig> queryBelongToCurrentInstancePropertyListByKeys(QueryPropertyConfigDTO configDto) {
        LogUtil.printSerializeOnlineLogs("configDto: ", configDto);
        final String projectId = configDto.getProjectId();
        List<String> keys = configDto.getKeys();
        if (CollectionUtils.isEmpty(keys)) {
            return Collections.emptyList();
        }

        final MetaClassInstance instance = internalUmlService.fetchInstance(configDto.getInstanceId(), projectId);
        if (instance == null) {
            return Collections.emptyList();
        }
        // 筛选属于当前模型的属性
        List<String> belongToCurrentInstanceProperties = keys.stream().filter(it ->
                elementCheckService.canBePropertyOwner(projectId, it, instance)).collect(Collectors.toList());

        List<PropertyConfigDto> configs = belongToCurrentInstanceProperties.stream().map(key -> {
            PropertyConfigDto dto = new PropertyConfigDto();
            dto.setKey(key);
            dto.setStereotype(internalUmlService.checkIsStereotypeProperty(projectId, key));
            return dto;
        }).collect(Collectors.toList());
        // 根据排序需求，先查找stereotype的attribute，再查找元类的attribute
        List<PropertyConfig> infos = createPropertyConfigByBatch(projectId, instance, configs, null);
        propertyFixedOrderSort(infos);
        return infos;
    }

    @NotNull
    public List<PropertyConfigDto> queryConfigDtoList(String projectId, MetaClassInstance instance) {
        LogUtil.printSerializeOnlineLogs("queryConfigDtoList -> projectId: {}, instance: {}", projectId, instance);
        final Collection<String> appliedStereotypes = instance.getAppliedStereotypes();
        if (appliedStereotypes.isEmpty()) {
            List<MetaClassInstance> stereotypeList = internalUmlService.queryListInstanceProperty(projectId, instance, UMLDefinitionConstants.Element_appliedStereotype);
            if (CollectionUtils.isNotEmpty(stereotypeList)) {
                appliedStereotypes.addAll(stereotypeList.stream().map(BasicRElement::getId).collect(Collectors.toList()));
            }
        }
        final Map<String, List<String>> customizationProperties = this.customizationService
                .queryCustomizationProperties(projectId, Collections.singletonList(instance));
        final List<MetaClassInstance> stereotypes = this.internalUmlService
                .fetchInstanceByIds(new ArrayList<>(appliedStereotypes), projectId);
        Set<String> givenTypes = internalUmlService.getGivenTypes(projectId, instance);
        final List<PropertyConfigDto> infos = new ArrayList<>();
        final List<String> stereotypePropertyIds;
        if (CollectionUtils.isNotEmpty(stereotypes)) {
            stereotypePropertyIds = internalPropertyService.queryStereoProperties(projectId,
                    stereotypes);
            // 部分元素的部分属性并不需要要展示
            if (givenTypes.contains(UMLDefinitionConstants.TableAndMatrix_DiagramTable)) {
                stereotypePropertyIds.removeIf(it -> StringUtils.equals(it, UMLDefinitionConstants.TableAndMatrix_DiagramTable_rowElements)
                        || StringUtils.equals(it, UMLDefinitionConstants.TableAndMatrix_DiagramTable_columnIds)
                        || StringUtils.equals(it, UMLDefinitionConstants.TableAndMatrix_DiagramTable_rowsOrder));
            }
            if (givenTypes.contains(UMLDefinitionConstants.SysML_ItemFlow)) {
                stereotypePropertyIds.removeIf(it -> StringUtils.equals(it, UMLDefinitionConstants.SysML_ItemFlow_activities));
            }
            if (givenTypes.contains(UMLDefinitionConstants.Customization_DataMapping)) {
                stereotypePropertyIds.removeIf(it -> StringUtils.equals(it,
                        UMLDefinitionConstants.Customization_DataMapping_mappingConfiguration));
            }
            if (givenTypes.contains(UMLDefinitionConstants.NumberOwner)) {
                stereotypePropertyIds.removeIf(it -> StringUtils.equals(it,
                        UMLDefinitionConstants.NumberOwner_customNumberingData));
            }
            infos.addAll(stereotypePropertyIds.stream().map(property -> {
                PropertyConfigDto dto = new PropertyConfigDto();
                dto.setType("");
                dto.setKey(property);
                dto.setStereotype(true);
                return dto;
            }).collect(Collectors.toList()));
        } else {
            stereotypePropertyIds = new ArrayList<>();
        }

        if (!customizationProperties.isEmpty()) {
            final List<String> allCustomizationProperties = customizationProperties.values().stream()
                    .flatMap(Collection::stream)
                    .distinct()
                    .collect(Collectors.toList());
            final List<PropertyConfigDto> propertyConfigDtoList = allCustomizationProperties.stream()
                    .filter(propertyId -> !stereotypePropertyIds.contains(propertyId))
                    .map(propertyId -> {
                        PropertyConfigDto dto = new PropertyConfigDto();
                        dto.setType("");
                        dto.setKey(propertyId);
                        dto.setStereotype(true);
                        return dto;
                    }).collect(Collectors.toList());
            infos.addAll(propertyConfigDtoList);
        }
        final List<MetaClassInstance> attributes = this.internalUmlService
                .queryMetaClassAndBaseClassPropertyList(Collections.singletonList(instance), projectId,
                        false, true, true);
        if (CollectionUtils.isNotEmpty(attributes)) {
            infos.addAll(attributes.stream()
                    .filter(it -> managerConfig.getPropertyConfigs().containsKey(it.getId()))
                    .map(it -> {
                        PropertyConfigDto dto = new PropertyConfigDto();
                        dto.setType("");
                        dto.setKey(it.getId());
                        return dto;
                    })
                    .collect(Collectors.toList()));
        } else {
            log.error("未找到属性列表，instanceId:{}", instance.getId());
        }
        Set<String> instanceTypeIds = this.internalUmlService.getGivenTypes(projectId, instance);
        List<MetaClassInstance> customization = elementPropertyService.queryPropertyRelationInstanceBatch(projectId,
                new ArrayList<>(instanceTypeIds), UMLDefinitionConstants.Customization_Customization_customizationTarget);
        if (CollectionUtils.isNotEmpty(customization)) {
            List<MetaClassInstance> driverInstances = new ArrayList<>();
            customization.forEach(it -> {
                List<MetaClassInstance> children = internalUmlService.getChildrenCascadeByClassifierIds(projectId, it
                        ,
                        Stream.of(UMLDefinitionConstants.CUSTOMIZATION_DERIVED_PROPERTY_SPECIFICATION).collect(Collectors.toList()), false);
                driverInstances.addAll(children);
            });
            if (CollectionUtils.isNotEmpty(driverInstances)) {
                infos.addAll(driverInstances.stream()
                        .map(it -> {
                            PropertyConfigDto dto = new PropertyConfigDto();
                            dto.setKey(it.getId());
                            dto.setType(DERIVED_PROPERTY_SPECIFICATION);
                            return dto;
                        })
                        .collect(Collectors.toList()));
            }
        }
        // 过滤Abstraction_mapping属性
        return infos.stream().filter(info ->
                        !StringUtils.equals(info.getKey(), UMLDefinitionConstants.Abstraction_mapping))
                .collect(Collectors.toList());
    }

    /**
     * 填充属性配置其它字段
     *
     * @param projectId
     * @param propertyConfig
     */
    public void fillConfigData(@NotNull String projectId, PropertyConfig propertyConfig) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, propertyConfig: {}", projectId, propertyConfig);
        if (propertyConfig.getDisplayLevel() == null) {
            propertyConfig.setDisplayLevel(1);
        }

        if (propertyConfig.getDataType() == null) {
            String dataType = internalUmlService.queryPropertyDataType(projectId, propertyConfig.getKey());
            propertyConfig.setDataType(dataType == null ? TypeEnum.STRING.getName() : dataType);
        }

        if (propertyConfig.getIsMultiplicity() == null) {
            propertyConfig.setIsMultiplicity(
                    internalUmlService.isMultiplicity(projectId, propertyConfig.getKey()));
        }
    }

    /**
     * 构建propertyConfig对象
     *
     * @param projectId
     * @param attribute          元模型或构造型的属性实例
     * @param dto
     * @param instance           元模型或构造型实例
     * @param mofResultContainer 必须包含attribute的TypedElement_type
     * @return com.huawang.mdesign.model.service.config.PropertyConfig
     * @author xz
     * @date 2023/05/24 16:09
     */
    @Nullable
    public PropertyConfig initConfig(String projectId,
                                     @NotNull MetaClassInstance attribute,
                                     @NotNull PropertyConfigDto dto,
                                     MetaClassInstance instance,
                                     @NotNull MofResultContainer mofResultContainer) {
        return propertyConfigService.initConfig(projectId, attribute, dto, instance, mofResultContainer);
    }

    /**
     * Property_defaultValue属性为枚举时，填充items，使前端组件可以适配为下拉选框。
     *
     * @param projectId
     * @param propertyConfig
     * @return void
     * @author baibf
     * @date 2023/02/23 15:17
     */
    private void setDefaultValueItemType(String projectId, PropertyConfig propertyConfig, MetaClassInstance attribute) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, propertyConfig: {}, attribute: {}", projectId, propertyConfig,
                attribute);
        final String propertyKey = propertyConfig.getKey();
        if (!Objects.equals(UMLDefinitionConstants.Property_defaultValue, propertyKey)) {
            return;
        }

        MetaClassInstance type =
                internalUmlService.queryInstanceProperty(projectId, attribute,
                        UMLDefinitionConstants.TypedElement_type);
        if (Objects.nonNull(type) && internalUmlService.checkInstanceType(projectId, type,
                UMLDefinitionConstants.Enumeration)) {
            propertyConfig.setItemType(ItemTypeEnum.ENUM_ITEM.getValue());
        }
    }

    /**
     * 批量更新propertyConfig内容
     *
     * @param projectId
     * @param instance
     * @param attributes
     * @param displayLevel
     * @return java.util.List<com.huawang.mdesign.model.service.config.PropertyConfig>
     * @author xz
     * @date 2023/05/24 16:12
     */
    @NotNull
    public List<PropertyConfig> createPropertyConfigByBatch(@NotNull final String projectId,
                                                            @NotNull MetaClassInstance instance,
                                                            @NotNull List<PropertyConfigDto> attributes,
                                                            Integer displayLevel) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, instance: {}, attributes: {}, displayLevel: {}", projectId, instance,
                attributes, displayLevel);
        //批量查询属性值
        Map<String, MofPropertyInfo> propertyValues = internalUmlService.queryPropertyByKeys(projectId, instance,
                attributes.stream().map(PropertyConfigDto::getKey).collect(Collectors.toList()));
        //兼容矩阵老数据
        propertyConfigService.processRelationCriterionInfo(propertyValues.get(UMLDefinitionConstants.Customization_MetaTypeConfig_diagramConfig), "diagramMatrixConfig",
                UMLDefinitionConstants.TableAndMatrix_DiagramMatrix_relationCriterion);
        propertyConfigService.processRelationCriterionInfoFromList(propertyValues.get(UMLDefinitionConstants.TableAndMatrix_DiagramMatrix_relationCriterion));
        propertyConfigService.processRelationCriterionInfoFromList(propertyValues.get(UMLDefinitionConstants.CUSTOMIZATION_DERIVED_EXPRESSION));
        //兼容追溯图老数据
        propertyConfigService.processRelationCriterionInfo(propertyValues.get(UMLDefinitionConstants.Customization_MetaTypeConfig_diagramConfig), "diagramMapConfig",
                UMLDefinitionConstants.TableAndMatrix_DiagramMap_relationCriterion);
        propertyConfigService.processRelationCriterionInfoFromList(propertyValues.get(UMLDefinitionConstants.TableAndMatrix_DiagramMap_relationCriterion));

        Map<String, MetaClassInstance> propertyInstanceMap = internalUmlService.fetchInstanceByIds(
                        attributes.stream().map(PropertyConfigDto::getKey).collect(Collectors.toList()), projectId)
                .stream().collect(Collectors.toMap(BasicRElement::getId, it -> it, (a, b) -> a));
        if (propertyValues.size() != attributes.size()) {
            log.error("查询模型属性值列表大小不一致,模型id:{},请求大小:{},返回大小:{}", instance.getId(), attributes.size(), propertyValues.size());
            log.error("缺失的属性:{}", attributes.stream().map(PropertyConfigDto::getKey).filter(it -> !propertyValues.containsKey(it)).collect(Collectors.toList()));
        }

        final List<MetaClassInstance> properties = attributes.stream()
                .map(it -> propertyInstanceMap.get(it.getKey()))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        final QueryPropertyForm queryPropertyForm = this.internalUmlService
                .getQueryPropertyForm(properties, Stream.of(UMLDefinitionConstants.TypedElement_type,
                        UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.StructuralFeature_isReadOnly).collect(Collectors.toList()));
        final MofResultContainer mofResultContainer = this.internalUmlService.queryProperty(projectId, queryPropertyForm);
        return createPropertyConfigByBatch(projectId, instance, attributes,
                propertyValues, propertyInstanceMap, mofResultContainer, displayLevel);

    }

    /**
     * 批量更新propertyConfig内容
     *
     * @param projectId
     * @param instance
     * @param attributes
     * @param propertyValues
     * @param displayLevel
     * @return java.util.List<com.huawang.mdesign.model.service.config.PropertyConfig>
     * @author xz
     * @date 2023/05/24 16:12
     */
    @NotNull
    public List<PropertyConfig> createPropertyConfigByBatch(@NotNull final String projectId,
                                                            @NotNull MetaClassInstance instance,
                                                            @NotNull List<PropertyConfigDto> attributes,
                                                            Map<String, MofPropertyInfo> propertyValues,
                                                            Map<String, MetaClassInstance> propertyInstanceMap,
                                                            MofResultContainer mofResultContainer,
                                                            Integer displayLevel) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, instance: {}, attributes: {}, propertyValues: {}, propertyInstanceMap: {}, displayLevel: {}",
                projectId, instance, attributes, propertyValues, propertyInstanceMap, displayLevel);
        if (propertyValues.size() != attributes.size()) {
            log.error("查询模型属性值列表大小不一致,模型id:{},请求大小:{},返回大小:{}", instance.getId(), attributes.size(), propertyValues.size());
            log.error("缺失的属性:{}", attributes.stream().map(PropertyConfigDto::getKey).filter(it -> !propertyValues.containsKey(it)).collect(Collectors.toList()));
        }

        Set<String> numberProperties = globalNumberCache.getNumberProperties(projectId);

        return attributes.stream().filter(it -> !UMLDefinitionConstants.TableAndMatrix_DiagramMatrix_dependencyCriteria.equals(it.getKey())).map(propertyConfigDto -> {
            MetaClassInstance property = propertyInstanceMap.get(propertyConfigDto.getKey());
            if (property == null) {
                return null;
            }

            PropertyConfig newPropertyConfig = initConfig(projectId, property, propertyConfigDto, instance, mofResultContainer);
            if (newPropertyConfig == null) {
                return null;
            }

            if (displayLevel != null && newPropertyConfig.getDisplayLevel() != null && newPropertyConfig.getDisplayLevel() > displayLevel) {
                return null;
            }

            MofPropertyInfo mofPropertyInfo = propertyValues.get(propertyConfigDto.getKey());
            if (mofPropertyInfo == null) {
                if (Objects.equals(propertyConfigDto.getType(), DERIVED_PROPERTY_SPECIFICATION)) {
                    newPropertyConfig.setUpper("1");
                    return newPropertyConfig;
                }
                return null;
            }
            if (CollectionUtils.isNotEmpty(numberProperties) && numberProperties.contains(propertyConfigDto.getKey())) {
                newPropertyConfig.setIsNumberProperty(true);
            }

            final PropertyQueryParameter parameter = PropertyQueryParameter.builder()
                    .projectId(projectId)
                    .instance(instance)
                    .dataType(newPropertyConfig.getDataType())
                    .key(newPropertyConfig.getKey())
                    .build();
            PropertyValueVo valueVo = getPropertyValue(parameter, mofPropertyInfo);
            initPropertyValue(newPropertyConfig, valueVo, projectId, instance);
            newPropertyConfig.setNullable(getNullable(mofPropertyInfo.getLower(),
                    mofPropertyInfo.getPropertyName()));
            newPropertyConfig.setUpper(StringUtils.isEmpty(mofPropertyInfo.getUpper()) ? "1" : mofPropertyInfo.getUpper());

            return newPropertyConfig;
        }).filter(Objects::nonNull).collect(Collectors.toList());

    }

    /**
     * 判断指定属性是否能置为null
     *
     * @param lower
     * @param propertyKey
     * @return boolean
     * @author xz
     * @date 2023/05/24 16:16
     */
    public boolean getNullable(Integer lower, String propertyKey) {
        LogUtil.printOnlineLogs("propertyKey: {}, lower: {}", propertyKey, lower);
        boolean nullable = false;
        if (lower != null && lower == 0) {
            nullable = !StringUtils.equals(propertyKey, UMLDefinitionConstants.Element_owner)
                    && !StringUtils.equals(propertyKey, UMLDefinitionConstants.ActivityNode_activity)
                    && !StringUtils.equals(propertyKey, UMLDefinitionConstants.Property_datatype);
        } else {
            List<String> specificAttributes = Arrays.asList(UMLDefinitionConstants.CallBehaviorAction_behavior,
                    UMLDefinitionConstants.CallOperationAction_operation,
                    UMLDefinitionConstants.CreateObjectAction_classifier,
                    UMLDefinitionConstants.ReadExtentAction_classifier,
                    UMLDefinitionConstants.StructuralFeatureAction_structuralFeature,
                    UMLDefinitionConstants.SendSignalAction_signal,
                    UMLDefinitionConstants.TableAndMatrix_DiagramTable_additionalElements,
                    UMLDefinitionConstants.ActiveImage_ActiveElement,
                    UMLDefinitionConstants.ActiveImage_OnClick,
                    UMLDefinitionConstants.InformationFlow_conveyed,
                    UMLDefinitionConstants.Customization_Customization_applyToSource,
                    UMLDefinitionConstants.Customization_Customization_applyToTarget,
                    UMLDefinitionConstants.TableAndMatrix_DiagramMatrix_removedRowElements,
                    UMLDefinitionConstants.TableAndMatrix_DiagramMatrix_removedColumnElements,
                    UMLDefinitionConstants.TableAndMatrix_DiagramTable_excludedElements,
                    UMLDefinitionConstants.Customization_ElementInstanceFilter_Element
            );
            if (specificAttributes.contains(propertyKey)) {
                nullable = true;
            }
        }

        return nullable;
    }

    @Autowired
    private PropertyConfigService propertyConfigService;

    @NotNull
    public PropertyValueVo getPropertyValues(final PropertyQueryParameter parameter,
                                             @Nullable MofPropertyInfo mofPropertyInfo) {
        String dataType = parameter.getDataType();
        PropertyValueVo valueVo = new PropertyValueVo();
        valueVo.setDataType(dataType);
        valueVo.setKey(parameter.getKey());

        return Optional.ofNullable(Optional.ofNullable(mofPropertyInfo)
                        .map(e -> propertyManager.queryCustomPropertyValue(parameter, e.getValues()))
                        .orElse(propertyManager.queryValue(parameter)))
                .map(v -> {
                    Collection<?> collection = Optional.of(v)
                            .filter(Collection.class::isInstance)
                            .map(Collection.class::cast)
                            .filter(CollectionUtils::isNotEmpty)
                            .orElse(null);

                    if (Objects.equals(dataType, TypeEnum.INSTANCE.getName())) {
                        //collection
                        Optional.ofNullable(collection)
                                .map(e -> e.stream()
                                        .map(it -> it instanceof MetaClassInstance ? ((MetaClassInstance) it).getId() : it)
                                        .collect(Collectors.toList()))
                                .filter(CollectionUtils::isNotEmpty)
                                .ifPresent(valueVo::setValue);

                        //instance
                        String projectId = parameter.getProjectId();
                        MetaClassInstance instance = (MetaClassInstance) Optional.of(v)
                                .filter(MetaClassInstance.class::isInstance)
                                .orElse(null);

                        Optional.ofNullable(instance)
                                .filter(e -> internalUmlService.checkInstanceType(projectId, e,
                                        UMLDefinitionConstants.ValueSpecification))
                                .ifPresent(e -> valueVo.setValueSpecificationInfo(
                                        internalSpecificationService.queryValueFromValueSpecification(projectId, e)));

                        Optional.ofNullable(instance)
                                .map(BasicRElement::getId)
                                .ifPresent(valueVo::setValue);
                    } else {
                        Optional.ofNullable(collection)
                                .map(e -> e.stream()
                                        .filter(it -> !(it instanceof MetaClassInstance))
                                        .collect(Collectors.toList()))
                                .filter(CollectionUtils::isNotEmpty)
                                .ifPresent(valueVo::setValue);

                        Optional.of(v).filter(e -> CollectionUtils.isEmpty(collection)).ifPresent(valueVo::setValue);
                    }
                    return valueVo;
                }).orElse(valueVo);
    }

    /**
     * 获取属性值vo
     *
     * @param parameter
     * @return
     */
    @Nullable
    public PropertyValueVo getPropertyValue(final PropertyQueryParameter parameter,
                                            @Nullable MofPropertyInfo mofPropertyInfo) {
        return propertyConfigService.getPropertyValue(parameter, mofPropertyInfo);
    }


    public Map<String, PropertyValueVo> getBatchPropertyValues(final List<PropertyQueryParameter> parameters) {
        LogUtil.printSerializeOnlineLogs("parameters: ", parameters);
        final String projectId = parameters.get(0).getProjectId();
        final String propertyKey = parameters.get(0).getKey();
        String dataType = parameters.get(0).getDataType();
        Map<String, Object> batchValues = propertyManager.queryBatchValues(projectId, propertyKey, parameters);
        final boolean isInstance = Objects.equals(dataType, TypeEnum.INSTANCE.getName());
        Map<String, PropertyValueVo> batchPropertyValue = new HashMap<>();
        batchValues.forEach((key, value) -> {
            PropertyValueVo valueVo = new PropertyValueVo();
            Object realValue = propertyConfigService.queryPropertyRealValue(projectId, valueVo, value, value,
                    isInstance);
            valueVo.setValue(realValue);
            valueVo.setDataType(dataType);
            valueVo.setKey(propertyKey);
            batchPropertyValue.put(key, valueVo);
        });
        return batchPropertyValue;
    }

    /**
     * 构建propertyConfig
     *
     * @param projectId
     * @param key
     * @param instance
     * @return com.huawang.mdesign.model.service.config.PropertyConfig
     * @author xz
     * @date 2023/12/21 14:43
     */
    @NotNull
    public PropertyConfig createPropertyConfig(String projectId, String key, MetaClassInstance instance) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, key: {}, instance: {}", projectId, key, instance);
        PropertyConfig newPropertyConfig = new PropertyConfig();
        final PropertyConfig propertyConfig = managerConfig.getPropertyConfigs().get(key);
        if (propertyConfig != null) {
            fillConfigData(projectId, propertyConfig);
            BeanUtils.copyProperties(propertyConfig, newPropertyConfig);
        } else {
            MetaClassInstance property = internalUmlService.fetchInstance(key, projectId);
            if (property != null) {
                final Map<String, ModelPropertyInfo> models = modelPropertyInfoService.createModelPropertyInfoMap(
                        projectId, Collections.singletonList(property),
                        Stream.of(UMLDefinitionConstants.StructuralFeature_isReadOnly, UMLDefinitionConstants.NamedElement_name,
                                        UMLDefinitionConstants.TypedElement_type)
                                .collect(Collectors.toList()));
                newPropertyConfig = internalPropertyService.initStereotypeProperty(projectId, models.get(property.getId()));
            }

        }

        final PropertyQueryParameter parameter = PropertyQueryParameter.builder()
                .projectId(projectId)
                .instance(instance)
                .dataType(newPropertyConfig.getDataType())
                .key(newPropertyConfig.getKey())
                .build();
        PropertyValueVo valueVo = getPropertyValue(parameter, null);
        initPropertyValue(newPropertyConfig, valueVo, projectId, instance);
        Integer lower = internalUmlService.queryPropertyLower(projectId, key);
        newPropertyConfig.setNullable(getNullable(lower, key));
        newPropertyConfig.setInstanceId(instance.getId());

        return newPropertyConfig;
    }

    @NotNull
    public Map<String, PropertyConfig> createBatchPropertyConfigs(String projectId, String propertyKey, List<MetaClassInstance> instances) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, propertyKey: {}, instances: {}", projectId, propertyKey, instances);
        PropertyConfig newPropertyConfig = new PropertyConfig();
        final PropertyConfig propertyConfig = managerConfig.getPropertyConfigs().get(propertyKey);
        if (propertyConfig != null) {
            fillConfigData(projectId, propertyConfig);
            BeanUtils.copyProperties(propertyConfig, newPropertyConfig);
        } else {
            MetaClassInstance property = internalUmlService.fetchInstance(propertyKey, projectId);
            if (property != null) {
                final Map<String, ModelPropertyInfo> models = modelPropertyInfoService.createModelPropertyInfoMap(
                        projectId, Collections.singletonList(property),
                        Stream.of(UMLDefinitionConstants.StructuralFeature_isReadOnly, UMLDefinitionConstants.NamedElement_name,
                                        UMLDefinitionConstants.TypedElement_type)
                                .collect(Collectors.toList()));
                newPropertyConfig = internalPropertyService.initStereotypeProperty(projectId, models.get(property.getId()));
            }

        }
        final String dataType = newPropertyConfig.getDataType();

        List<PropertyQueryParameter> parameters = instances.stream().map(instance -> PropertyQueryParameter.builder()
                .projectId(projectId)
                .instance(instance)
                .dataType(dataType)
                .key(propertyKey)
                .build()).collect(Collectors.toList());

        Map<String, PropertyValueVo> batchPropertyValues = getBatchPropertyValues(parameters);

        Map<String, PropertyConfig> propertyConfigMap = new HashMap<>();
        PropertyConfig finalNewPropertyConfig = newPropertyConfig;
        instances.forEach(instance -> {
            PropertyConfig propertyConfigInfo = new PropertyConfig();
            BeanUtils.copyProperties(finalNewPropertyConfig, propertyConfigInfo);
            String instanceId = instance.getId();
            PropertyValueVo valueVo = batchPropertyValues.get(instanceId);
            initPropertyValue(propertyConfigInfo, valueVo, projectId, instance);
            Integer lower = internalUmlService.queryPropertyLower(projectId, propertyKey);
            propertyConfigInfo.setNullable(getNullable(lower, propertyKey));
            propertyConfigInfo.setInstanceId(instanceId);
            propertyConfigMap.put(instanceId, propertyConfigInfo);
        });
        return propertyConfigMap;
    }

    @NotNull
    public List<PropertyValue> queryPropertyValues(String projectId,
                                                   String tableId,
                                                   TableColumnInfo columnInfo,
                                                   List<MetaClassInstance> instances) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, tableId: {}, columnInfo: {}, instances: {}", projectId, tableId,
                columnInfo, instances);
        List<PropertyQueryParameter> parameters = instances.stream()
                .map(instance -> PropertyQueryParameter.builder()
                        .projectId(projectId)
                        .instance(instance)
                        .dataType(columnInfo.getDataType())
                        .key(columnInfo.getKey())
                        .tableId(tableId)
                        .build()).collect(Collectors.toList());
        Map<String, PropertyValueVo> batchPropertyValues = getBatchPropertyValues(parameters);
        return instances.stream().map(instance -> {
            PropertyValue value = new PropertyValue();
            value.setInstanceId(instance.getId());
            value.setDataType(columnInfo.getDataType());
            value.setKey(columnInfo.getKey());
            PropertyValueVo valueVo = batchPropertyValues.get(instance.getId());
            if (valueVo != null) {
                value.setValue(valueVo.getValue());
                value.setValueSpecificationInfo(valueVo.getValueSpecificationInfo());
            }

            return value;
        }).collect(Collectors.toList());
    }

    /**
     * 查询多个模型的多个属性值
     *
     * @param dto
     * @return
     */
    @NotNull
    public List<MultiPropertyValueVo> queryMultiPropertyValue(QueryMultiPropertyValueDTO dto) {
        LogUtil.printSerializeOnlineLogs("queryMultiPropertyValue -> dto: ", dto);
        final String projectId = dto.getProjectId();
        List<MultiPropertyValueVo> result = new ArrayList<>();
        final Map<String, MetaClassInstance> metaClassInstanceMap = CollectionUtils.isNotEmpty(dto.getInstances()) ?
                this.internalUmlService.fetchInstanceByIds(
                        dto.getInstances().stream()
                                .map(QueryPropertyValueDTO::getInstanceId)
                                .collect(Collectors.toList()),
                        dto.getProjectId()
                ).stream().collect(Collectors.toMap(BasicRElement::getId, Function.identity(), (a, b) -> a)) :
                Collections.emptyMap();
        for (QueryPropertyValueDTO modelPropertyDto : dto.getInstances()) {
            MultiPropertyValueVo propertyValueVo = new MultiPropertyValueVo();
            final MetaClassInstance instance = metaClassInstanceMap.get(modelPropertyDto.getInstanceId());
            if (instance == null) {
                continue;
            }
            List<PropertyValueVo> values = new ArrayList<>(modelPropertyDto.getKeys().size());
            propertyValueVo.setInstanceId(modelPropertyDto.getInstanceId());
            List<MofPropertyInfo> propertyInfos = new ArrayList<>(internalUmlService.queryPropertyByKeys(projectId,
                    instance, modelPropertyDto.getKeys()).values());
            for (MofPropertyInfo property : propertyInfos) {
                final PropertyQueryParameter parameter = PropertyQueryParameter.builder()
                        .projectId(projectId)
                        .instance(instance)
                        .key(property.getPropertyName())
                        .dataType(property.getDataType())
                        .build();
                PropertyValueVo valueVo = getPropertyValue(parameter, property);
                values.add(valueVo);
            }

            propertyValueVo.setProperties(values);
            result.add(propertyValueVo);
        }

        return result;
    }

    /**
     * @param dto
     * @return java.util.List<com.huawang.mdesign.model.service.vo.MultiPropertyValueVo>
     * @author xz
     * @date 2023/12/08 09:52
     */
    @NotNull
    public List<MultiPropertyValueVo> queryPropertyValueBatch(QueryMultiPropertyValueDTO dto) {
        LogUtil.printSerializeOnlineLogs("queryPropertyValueBatch -> dto: ", dto);
        final String projectId = dto.getProjectId();
        List<MultiPropertyValueVo> result = new ArrayList<>();
        final Map<String, MetaClassInstance> metaClassInstanceMap =
                internalUmlService.fetchInstances(dto.getInstances().stream()
                                .map(QueryPropertyValueDTO::getInstanceId).collect(Collectors.toList()),
                        projectId);

        Map<MetaClassInstance, List<String>> modelKeyMap = new HashMap<>();
        for (QueryPropertyValueDTO instanceDto : dto.getInstances()) {
            Optional.ofNullable(instanceDto)
                    .map(QueryPropertyValueDTO::getInstanceId)
                    .filter(StringUtils::isNotBlank)
                    .map(metaClassInstanceMap::get)
                    .ifPresent(e -> modelKeyMap.put(e, instanceDto.getKeys()));
        }

        MofResultContainer container = internalUmlService.queryPropertyByModelKeyMap(projectId, modelKeyMap);
        for (MetaClassInstance instance : metaClassInstanceMap.values()) {
            MultiPropertyValueVo propertyValueVo = new MultiPropertyValueVo();
            List<PropertyValueVo> values = new ArrayList<>(container.getMofPropertyInfoMap().size());
            propertyValueVo.setInstanceId(instance.getId());
            for (MofPropertyInfo property : container.getMofPropertyInfoMap().get(instance.getId()).values()) {
                final PropertyQueryParameter parameter = PropertyQueryParameter.builder()
                        .projectId(projectId)
                        .instance(instance)
                        .key(property.getPropertyName())
                        .dataType(property.getDataType())
                        .build();
                PropertyValueVo valueVo = getPropertyValue(parameter, property);
                values.add(valueVo);
            }

            propertyValueVo.setProperties(values);
            result.add(propertyValueVo);
        }

        return result;
    }

    /**
     * 校验模型类型
     *
     * @param instanceId 模型id
     * @param typeId     模型类型id
     * @return
     */
    public boolean checkInstanceType(@NotNull final String projectId,
                                     @NotNull final String instanceId,
                                     @NotNull final String typeId) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, instanceId: {}, typeId: {}", projectId, instanceId, typeId);
        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (instance == null) {
            return false;
        }

        return internalUmlService.checkInstanceType(projectId, instance, typeId);
    }

    /**
     * 批量删除模型
     *
     * @param deleteModelDto
     * @return com.huawang.mdesign.model.service.vo.ModelResultVo
     * @author xz
     * @date 2023/05/24 17:38
     */
    @NotNull
    public ModelResultVo deleteByIds(DeleteModelDTO deleteModelDto) {
        LogUtil.printSerializeOnlineLogs("deleteModelDto: ", deleteModelDto);
        final String projectId = deleteModelDto.getProjectId();
        ModelResultVo modelResultVo = new ModelResultVo();
        LocalTransaction transaction = transactionService.createTransaction(projectId, DELETE_MODEL);
        try {
            businessDeleteByIds(projectId, deleteModelDto.getIds());
            List<String> deleteObjects = new ArrayList<>(transaction.getDeleteObjects());
            deleteExternalDataMapping(projectId,deleteObjects);
            transactionService.commit(projectId);
            InstanceVoUtils.fillDeleteResultVo(deleteModelDto, modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.SERVICE_ERROR, e);
        }

        return modelResultVo;
    }

    public void businessDeleteByIds(@NotNull String projectId, @NotNull List<String> deleteIds) {
        List<MetaClassInstance> instanceList = internalUmlService.fetchInstanceByIds(deleteIds, projectId);
        deleteModelPreProcessor(projectId, instanceList);
        instanceList.forEach(instance -> {
            elementLinkedDelete(projectId, instance);
            slotValueLinkedDelete(projectId, instance);
        });
        deleteService.deleteModels(projectId, deleteIds);
    }

    /**
     * 删除模型前置处理
     *
     * @param projectId
     * @param instances
     * @return void
     * @author baibf
     * @date 2024/06/11 17:08
     */
    private void deleteModelPreProcessor(String projectId, List<MetaClassInstance> instances) {
        // 从当前模型查询所有子节点
        final List<MetaClassInstance> allDeleteInstanceList = internalUmlService.getChildrenCascadeCreatedInteractive(projectId, instances);
        globalNumberGenerator.deleteElementRemoveNumberPropertyLog(projectId, allDeleteInstanceList);
    }


    /**
     * slotValue关联删除
     *
     * @param projectId
     * @param instance
     * @return void
     * @author baibf
     * @date 2022/10/27 14:34
     */
    private void slotValueLinkedDelete(@NotNull String projectId, @Nullable MetaClassInstance instance) {
        LogUtil.printSerializeOnlineLogs("slotValueLinkedDelete -> projectId: {}, instance: {}", projectId, instance);
        if (instance == null) {
            return;
        }

        MetaClassInstance ownerInstance = internalUmlService.queryInstanceProperty(projectId, instance,
                UMLDefinitionConstants.Element_owner);
        if (Objects.nonNull(ownerInstance) && internalUmlService.checkInstanceType(projectId, ownerInstance,
                UMLDefinitionConstants.Slot)) {
            List<MetaClassInstance> slotValues = internalUmlService.queryListInstanceProperty(projectId,
                    ownerInstance, UMLDefinitionConstants.Slot_value);
            if (slotValues.size() == 1) {
                deleteService.deleteModel(projectId, ownerInstance.getId());
            }
        }
    }

    /**
     * 元素关联删除
     *
     * @param projectId
     * @param instance
     * @return void
     * @author xz
     * @date 2023/05/24 17:39
     */
    private void elementLinkedDelete(@NotNull String projectId, @Nullable MetaClassInstance instance) {
        LogUtil.printSerializeOnlineLogs("elementLinkedDelete -> projectId: {}, instance: {}", projectId, instance);
        if (instance == null) {
            return;
        }
        Set<String> givenTypes = internalUmlService.getGivenTypes(projectId, instance);

        if (givenTypes.contains(UMLDefinitionConstants.StateInvariant)) {
            deleteStateInvariant(projectId, instance);
        } else if (givenTypes.contains(UMLDefinitionConstants.ExtensionPoint)) {
            deleteExtensionPoint(projectId, instance);

        } else if (givenTypes.contains(UMLDefinitionConstants.InstanceSpecification)) {
            List<MetaClassInstance> instanceValues = internalUmlService.queryListInstanceProperty(projectId, instance,
                    UMLDefinitionConstants.A_instance_instanceValue_instanceValue);
            if (CollectionUtils.isEmpty(instanceValues)) {
                return;
            }

            instanceValues.forEach(instanceValue -> slotValueLinkedDelete(projectId, instanceValue));
            deleteService.deleteModels(projectId, instanceValues.stream().map(BasicRElement::getId).collect(Collectors.toList()));

        } else if (givenTypes.contains(UMLDefinitionConstants.Customization_ConstraintProperty)) {
            deleteConstraintProperty(projectId, instance);
        } else if (givenTypes.contains(UMLDefinitionConstants.SysML_Block)) {
            // 删除Block时，同时删除应用该Block作为类型的部件属性
            final ModelPropertyInfo instanceModel = modelPropertyInfoService.createSimpleModelPropertyInfo(projectId,
                    instance, Stream.of(UMLDefinitionConstants.SysML_Block_usedAsType).collect(Collectors.toList()));
            final List<MetaClassInstance> propertyList =
                    instanceModel.queryListInstanceValue(UMLDefinitionConstants.SysML_Block_usedAsType);
            final List<String> partPropertyIds = propertyList.stream()
                    .filter(propertyInstance -> internalUmlService.checkInstanceType(projectId, propertyInstance,
                            UMLDefinitionConstants.Customization_PartProperty))
                    .map(BasicRElement::getId).collect(Collectors.toList());
            deleteService.deleteModels(projectId, partPropertyIds);
        } else if (givenTypes.contains(UMLDefinitionConstants.Classifier)) {
            List<MetaClassInstance> attributeList = internalUmlService.queryListInstanceProperty(projectId, instance,
                    UMLDefinitionConstants.Classifier_attribute);
            if (CollectionUtils.isEmpty(attributeList)) {
                return;
            }
            List<MetaClassInstance> associationList = attributeList.stream().map(attribute ->
                            internalUmlService.queryInstanceProperty(projectId, attribute,
                                    UMLDefinitionConstants.Property_association)).filter(Objects::nonNull)
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(associationList)) {
                return;
            }
            List<MetaClassInstance> memberEndList = associationList.stream().flatMap(association ->
                    internalUmlService.queryListInstanceProperty(projectId, association,
                            UMLDefinitionConstants.Association_memberEnd).stream()).collect(Collectors.toList());
            memberEndList.addAll(associationList);
            deleteService.deleteModels(projectId, memberEndList.stream().map(BasicRElement::getId).collect(Collectors.toList()));

        } else if (givenTypes.contains(UMLDefinitionConstants.Generalization)) {
            deleteGeneralization(projectId, instance);
        } else if (givenTypes.contains(UMLDefinitionConstants.ActivityEdge)) {
            informationFlowService.updateInformationFlowByDeletedActivityEdge(projectId, instance);
        } else if (givenTypes.contains(UMLDefinitionConstants.Pin)) {
            deletePin(projectId, instance);
        } else if (givenTypes.contains(UMLDefinitionConstants.Property)) {
            // property上有port，port为连接器一端，删除property，不删除port，但需要删除connector
            MetaClassInstance type = internalUmlService.queryInstanceProperty(projectId, instance, UMLDefinitionConstants.TypedElement_type);
            if (Objects.isNull(type)) {
                return;
            }
            List<MetaClassInstance> ownedPortList = internalUmlService.queryListInstanceProperty(projectId, type,
                    UMLDefinitionConstants.EncapsulatedClassifier_ownedPort);
            if (CollectionUtils.isEmpty(ownedPortList)) {
                return;
            }
            QueryPropertyForm queryPropertyForm = internalUmlService.getQueryPropertyForm(ownedPortList, UMLDefinitionConstants.ConnectableElement_end);
            MofResultContainer mofResultContainer = internalUmlService.queryProperty(projectId, queryPropertyForm);
            List<MetaClassInstance> endList = ownedPortList.stream().flatMap(part -> mofResultContainer.queryListInstanceProperty(part.getId(),
                    UMLDefinitionConstants.ConnectableElement_end).stream()).collect(Collectors.toList());
            Set<String> connectorIds = endList.stream().map(MetaClassInstance::getOwnerId).collect(Collectors.toSet());
            deleteService.deleteModels(projectId, new ArrayList<>(connectorIds));
        } else if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.Element)) {
            List<MetaClassInstance> elementValues = internalUmlService.queryListInstanceProperty(projectId, instance,
                    UMLDefinitionConstants.A_element_elementValue_elementValue);
            if (CollectionUtils.isEmpty(elementValues)) {
                return;
            }
            elementValues.forEach(elementValue -> slotValueLinkedDelete(projectId, elementValue));
            deleteService.deleteModels(projectId, elementValues.stream().map(BasicRElement::getId).collect(Collectors.toList()));
        } else {
            log.info("模型:{}的类型不为ExtensionPoint、InstanceSpecification、Customization_ConstraintProperty、SysML_Block" +
                    "Classifier、Generalization或Element， 无需进一步删除相关关联元素", instance.getId());
        }

    }
    /**
     * 删除datahub关联记录
     * @param projectId
     * @param instanceIds
     */
    private void deleteExternalDataMapping(String projectId, List<String> instanceIds) {
        LogUtil.printSerializeOnlineLogs("deleteExternalDataMapping -> projectId: {}, instanceIds: {}", projectId, instanceIds);

        List<ExternalDataMappingDO> externalDataMappingDOS = queryExternalDataMappingAccess.selectByInstanceIds(instanceIds);
        if (CollectionUtils.isNotEmpty(externalDataMappingDOS)) {
            List<ExternalMappingDataInfo> externalMappingDataInfos = ExternalMappingDataConverter.convertToInfo(externalDataMappingDOS);
            saveExternalDataMappingService.removeExternalDataMappings(projectId, externalMappingDataInfos);
        }
    }

    private void deletePin(@NotNull String projectId, @NotNull MetaClassInstance instance) {
        List<MetaClassInstance> deletedActivityEdges = new ArrayList<>();
        List<MetaClassInstance> incomings = internalUmlService.queryListInstanceProperty(projectId, instance,
                UMLDefinitionConstants.ActivityNode_incoming);
        if (CollectionUtils.isNotEmpty(incomings)) {
            deletedActivityEdges.addAll(incomings);
        }

        final List<MetaClassInstance> outgoings = internalUmlService.queryListInstanceProperty(projectId, instance, UMLDefinitionConstants.ActivityNode_outgoing);
        if (CollectionUtils.isNotEmpty(outgoings)) {
            deletedActivityEdges.addAll(outgoings);
        }

        deletedActivityEdges.forEach(deletedActivityEdge ->
                informationFlowService.updateInformationFlowByDeletedActivityEdge(projectId, deletedActivityEdge)
        );
    }

    private void deleteExtensionPoint(@NotNull String projectId, @NotNull MetaClassInstance instance) {
        LogUtil.printSerializeOnlineLogs("deleteExtensionPoint -> projectId: {}, instance: {}", projectId, instance);
        List<MetaClassInstance> extensions = internalUmlService.queryListInstanceProperty(projectId, instance,
                UMLDefinitionConstants.A_extensionLocation_extension_extension);
        List<String> extendIds = new ArrayList<>();
        extensions.forEach(extend -> {
            List<MetaClassInstance> extensionLocations = internalUmlService.queryListInstanceProperty(projectId,
                    extend, UMLDefinitionConstants.Extend_extensionLocation);
            if (extensionLocations.contains(instance) && extensionLocations.size() == 1) {
                extendIds.add(extend.getId());
            }

        });
        if (CollectionUtils.isNotEmpty(extendIds)) {
            deleteService.deleteModels(projectId, extendIds);
        }
    }

    private void deleteGeneralization(@NotNull String projectId, @NotNull MetaClassInstance instance) {
        LogUtil.printSerializeOnlineLogs("deleteGeneralization -> projectId: {}, instance: {}", projectId, instance);
        // 查询泛化关系的两端
        ModelPropertyInfo instanceModel = modelPropertyInfoService.createSimpleModelPropertyInfo(projectId, instance,
                Stream.of(UMLDefinitionConstants.DirectedRelationship_source,
                        UMLDefinitionConstants.DirectedRelationship_target).collect(Collectors.toList()));
        List<MetaClassInstance> sourceList = instanceModel.queryListInstanceValue(UMLDefinitionConstants.DirectedRelationship_source);
        List<MetaClassInstance> targetList = instanceModel.queryListInstanceValue(UMLDefinitionConstants.DirectedRelationship_target);
        if (CollectionUtils.isEmpty(sourceList) || CollectionUtils.isEmpty(targetList)) {
            return;
        }
        MetaClassInstance source = sourceList.get(0);
        MetaClassInstance target = targetList.get(0);

        // 查询分类器是source端的InstanceSpecification
        List<MetaClassInstance> instanceSpecifications = internalUmlService.queryListInstanceProperty(projectId, source,
                UMLDefinitionConstants.A_classifier_instanceSpecification_instanceSpecification);
        List<MetaClassInstance> attributes = internalUmlService.queryListInstanceProperty(projectId, target,
                UMLDefinitionConstants.Class_ownedAttribute);

        // 查询InstanceSpecification的slot
        List<ModelPropertyInfo> instanceSpecificationModels = modelPropertyInfoService.createModelPropertyInfoList(
                projectId, instanceSpecifications, Collections.singletonList(UMLDefinitionConstants.InstanceSpecification_slot));

        List<MetaClassInstance> slotList = instanceSpecificationModels.stream().flatMap(model ->
                model.queryListInstanceValue(UMLDefinitionConstants.InstanceSpecification_slot).stream()).collect(Collectors.toList());

        // 查询Slot的definingFeature
        List<ModelPropertyInfo> slotModels = modelPropertyInfoService.createModelPropertyInfoList(
                projectId, slotList, Collections.singletonList(UMLDefinitionConstants.Slot_definingFeature));
        // 删掉是target端的attribute所对应的slot
        slotModels.forEach(model -> {
            MetaClassInstance definingFeature = model.queryInstanceValue(UMLDefinitionConstants.Slot_definingFeature);
            if (attributes.contains(definingFeature)) {
                deleteService.deleteModel(projectId, model.getInstance().getId());
            }
        });
    }

    private void deleteConstraintProperty(@NotNull String projectId, @NotNull MetaClassInstance instance) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, instance: {}", projectId, instance);
        MetaClassInstance type = internalUmlService.queryInstanceProperty(projectId, instance,
                UMLDefinitionConstants.TypedElement_type);
        if (Objects.isNull(type)) {
            return;
        }
        List<MetaClassInstance> constraintParameters = internalUmlService.queryListInstanceProperty(projectId,
                type, UMLDefinitionConstants.EncapsulatedClassifier_ownedPort);
        if (CollectionUtils.isEmpty(constraintParameters)) {
            return;
        }
        MetaClassInstance owner = internalUmlService.queryInstanceProperty(projectId, instance,
                UMLDefinitionConstants.Element_owner);
        List<MetaClassInstance> ownedConnectors = internalUmlService.queryListInstanceProperty(projectId, owner,
                UMLDefinitionConstants.StructuredClassifier_ownedConnector);
        if (CollectionUtils.isEmpty(ownedConnectors)) {
            return;
        }
        List<MetaClassInstance> connectors = ownedConnectors.stream().map(it -> {
            List<MetaClassInstance> connectorEnds = internalUmlService.queryListInstanceProperty(projectId, it,
                    UMLDefinitionConstants.Connector_end);
            MetaClassInstance source = internalUmlService.queryInstanceProperty(projectId, connectorEnds.get(0),
                    UMLDefinitionConstants.ConnectorEnd_role);
            MetaClassInstance target = internalUmlService.queryInstanceProperty(projectId, connectorEnds.get(1),
                    UMLDefinitionConstants.ConnectorEnd_role);
            List<MetaClassInstance> partWithPortList = connectorEnds.stream().map(end ->
                    internalUmlService.queryInstanceProperty(projectId, end,
                            UMLDefinitionConstants.ConnectorEnd_partWithPort)).collect(Collectors.toList());
            if (partWithPortList.contains(instance)
                    && (constraintParameters.contains(source) || constraintParameters.contains(target))) {
                return it;
            }
            return null;
        }).filter(Objects::nonNull).collect(Collectors.toList());
        deleteService.deleteModels(projectId, connectors.stream().map(BasicRElement::getId).collect(Collectors.toList()));
    }

    /**
     * description:删除状态常量需要同时删除状态常量绑定的约束/ 约束对应的时间事件
     */
    private void deleteStateInvariant(@NotNull String projectId, @NotNull MetaClassInstance instance) {
        LogUtil.printSerializeOnlineLogs("deleteStateInvariant -> projectId: {}, instance: {}", projectId, instance);
        // 1.查询状态常量约束
        List<MetaClassInstance> constraints = internalUmlService.queryListInstanceProperty(
                projectId, instance, UMLDefinitionConstants.Element_constraints);
        List<String> relatedIds = constraints.stream().map(BasicRElement::getId).collect(Collectors.toList());

        List<MetaClassInstance> durationConstraints = constraints.stream().filter(it ->
                internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.DurationConstraint)).collect(Collectors.toList());
        List<MetaClassInstance> timeConstraints = constraints.stream().filter(it ->
                internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.TimeConstraint)).collect(Collectors.toList());

        // 2.查询约束对应时间事件
        relatedIds.addAll(getRelatedTimeEventsByConstraints(projectId, durationConstraints, true));
        relatedIds.addAll(getRelatedTimeEventsByConstraints(projectId, timeConstraints, false));
        if (CollectionUtils.isNotEmpty(relatedIds)) {
            deleteService.deleteModels(projectId, relatedIds);
        }
    }

    @NotNull
    private Set<String> getRelatedTimeEventsByConstraints(@NotNull String projectId,
                                                          @NotNull List<MetaClassInstance> constraints,
                                                          boolean isDurationConstraints) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, constraints: {}, isDurationConstraints: {}", projectId, constraints,
                isDurationConstraints);
        String specificationPropertyKey = isDurationConstraints ?
                UMLDefinitionConstants.DurationConstraint_specification : UMLDefinitionConstants.TimeConstraint_specification;
        String intervalMaxPropertyKey = isDurationConstraints ?
                UMLDefinitionConstants.DurationInterval_max : UMLDefinitionConstants.TimeInterval_max;
        String intervalMinPropertyKey = isDurationConstraints ?
                UMLDefinitionConstants.DurationInterval_min : UMLDefinitionConstants.TimeInterval_min;
        MofResultContainer constraintContainer = internalUmlService.getMofResultContainer(projectId, constraints, specificationPropertyKey);
        List<MetaClassInstance> specifications = constraints.stream().map(constraint ->
                constraintContainer.queryInstanceProperty(constraint.getId(), specificationPropertyKey)).collect(Collectors.toList());
        MofResultContainer specificationContainer = internalUmlService.getMofResultContainer(
                projectId, specifications, Stream.of(intervalMaxPropertyKey, intervalMinPropertyKey).collect(Collectors.toList()));
        List<MetaClassInstance> intervals = specifications.stream().flatMap(specification -> {
            MetaClassInstance intervalMax = specificationContainer.queryInstanceProperty(specification.getId(), intervalMaxPropertyKey);
            MetaClassInstance intervalMin = specificationContainer.queryInstanceProperty(specification.getId(), intervalMinPropertyKey);
            return Stream.of(intervalMax, intervalMin);
        }).filter(Objects::nonNull).collect(Collectors.toList());
        Map<MetaClassInstance, List<MetaClassInstance>> ancestorMap = internalUmlService.getAncestor(projectId, intervals);
        return ancestorMap.values().stream()
                .flatMap(Collection::stream)
                .filter(it -> internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.TimeEvent))
                .map(BasicRElement::getId)
                .collect(Collectors.toSet());
    }

    /**
     * 查询模型创建来源
     *
     * @param projectId
     * @param instanceIds
     * @return java.util.Map<java.lang.String, java.lang.Integer>
     * @author xz
     * @date 2023/05/24 17:49
     */
    @NotNull
    public Map<String, Integer> fetchFrom(final String projectId, final List<String> instanceIds) {
        LogUtil.printOnlineLogs("fetchFrom -> projectId: {}, instanceIds: {}", projectId, instanceIds);
        List<MetaClassInstance> instanceList = internalUmlService.fetchInstanceByIds(instanceIds, projectId);
        return instanceList.stream().filter(Objects::nonNull).collect(Collectors.toMap(BasicRElement::getId,
                b -> b.getModelCreatorType().getCreator(), (k, v) -> k));
    }

    /**
     * 查询某个模型拥有的模型
     *
     * @param projectId
     * @param instanceId
     * @return java.util.List<com.huawang.mdesign.model.service.vo.InstanceVo>
     * @author xz
     * @date 2023/05/24 17:50
     */
    @NotNull
    public List<InstanceVo> queryChildren(final String projectId, final String instanceId) {
        LogUtil.printOnlineLogs("queryChildren -> projectId: {}, instanceId: {}", projectId, instanceId);
        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(instance)) {
            throw AbortExecutionException.build(ErrorCode.PARAM_ERROR);
        }


        List<MetaClassInstance> ownedElements = internalUmlService.queryListInstanceProperty(
                projectId, instance, UMLDefinitionConstants.Element_ownedElement);
        if (CollectionUtils.isNotEmpty(ownedElements)) {

            Map<String, ModelPropertyInfo> modelPropertyInfoMap = modelPropertyInfoService.
                    makeFullModelPropertyInfo(projectId, new ArrayList<>(ownedElements));
            return modelPropertyInfoMap.values().stream().map(it -> makeInstanceVo(projectId, it)).collect(
                    Collectors.toList());
        }
        return Collections.emptyList();
    }


    /**
     * @param propertyConfigInfos
     * @return void
     * @description 属性信息按照指定名称排序
     * @author baibf
     * @date 2022/3/17
     */
    public void propertyFixedOrderSort(List<? extends PropertyConfig> propertyConfigInfos) {
        LogUtil.printSerializeOnlineLogs("propertyConfigInfos: ", propertyConfigInfos);
        List<String> orderList = Arrays.asList(
                UMLDefinitionConstants.NamedElement_name,
                UMLDefinitionConstants.NamedElement_namespace,
                UMLDefinitionConstants.NamedElement_qualifiedName,
                UMLDefinitionConstants.Element_owner,
                UMLDefinitionConstants.Element_appliedStereotype,
                UMLDefinitionConstants.Element_syncElement,
                UMLDefinitionConstants.Classifier_general);
        ModelInstanceUtil.diagramTableSortByColumn(orderList, propertyConfigInfos);
    }

    /**
     * 查询内部元素
     *
     * @param instanceId
     * @return
     */
    @NotNull
    public List<InnerElementVo> queryInnerElements(String projectId, String instanceId) {
        LogUtil.printSerializeOnlineLogs("queryInnerElements -> projectId: {}, instanceId: {}", projectId, instanceId);
        List<MetaClassInstance> results = new ArrayList<>();
        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (instance == null) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }

        if (internalUmlService.isMetaClass(projectId, instance)) {
            return Collections.emptyList();
        }

        if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.Package)
                || internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.Action)) {
            results.addAll(internalUmlService.queryListInstanceProperty(projectId, instance,
                    UMLDefinitionConstants.Element_ownedElement));
        } else if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.SysMLStructureDiagram)) {
            MetaClassInstance context = internalUmlService.queryInstanceProperty(projectId, instance, UMLDefinitionConstants.Diagram_context);
            if (context != null) {
                results.addAll(getAllAttributes(projectId, context));
            }

        } else {
            results.addAll(getAllAttributes(projectId, instance));
        }

        // 过滤掉Customization_NumberOwner构造型的数据
        results = results.stream().filter(it -> {
            MetaClassInstance classifier = internalUmlService.queryInstanceProperty(projectId,
                    it, UMLDefinitionConstants.InstanceSpecification_classifier);
            return Objects.isNull(classifier)
                    || !classifier.getId().equals(UMLDefinitionConstants.Customization_NumberOwner)
                    || !classifier.getId().equals(UMLDefinitionConstants.NumberOwner);
        }).collect(Collectors.toList());

        // 只有拥有泛化关系才被认为是继承而来的
        List<MetaClassInstance> inheritedMemberInstances = internalUmlService.queryListInstanceProperty(projectId,
                instance, UMLDefinitionConstants.Classifier_inheritedMember);
        Set<String> instanceIds = inheritedMemberInstances.stream().map(MetaClassInstance::getId)
                .collect(Collectors.toSet());

        return results.stream().map(it -> {
            InnerElementVo vo = new InnerElementVo();
            vo.setId(it.getId());
            if (instanceIds.contains(it.getId())) {
                vo.setIsDisplay(true);
            }

            return vo;
        }).collect(Collectors.toList());
    }

    @NotNull
    public List<CheckShapeDTO> checkInnerElements(String projectId, CheckShapeDTO shape) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, shape: {}", projectId, shape);
        List<CheckShapeDTO> result = new ArrayList<>();
        MetaClassInstance diagramInstance = internalUmlService.fetchExistInstance(shape.getModelId(), projectId);
        if (isIbdOrPar(diagramInstance)) {
            // 只校验属性和端口
            List<String> collect =
                    shape.getChildren().stream().filter(i -> !ShapeTypeEnum.EDGE.getName().equals(i.getShapeType()))
                            .map(CheckShapeDTO::getModelId).distinct().collect(Collectors.toList());
            List<MetaClassInstance> metaClassInstances = internalUmlService.fetchInstanceByIds(collect, projectId).stream()
                    .filter(i -> UMLDefinitionConstants.Property.equals(i.getMetaClass().getId())
                            || UMLDefinitionConstants.Port.equals(i.getMetaClass().getId())).collect(Collectors.toList());
            if (metaClassInstances.isEmpty()) {
                return result;
            }
            Map<String, MetaClassInstance> instanceMap = metaClassInstances.stream().collect(Collectors.toMap(MetaClassInstance::getId, i -> i));
            MetaClassInstance context = internalUmlService.queryInstanceProperty(projectId, diagramInstance, UMLDefinitionConstants.Diagram_context);
            if (context == null) {
                log.warn("context不存在:{}", diagramInstance.getId());
                return result;
            }

            List<MetaClassInstance> allAttributes = getAllAttributes(projectId, context);
            List<String> instanceIds = allAttributes.stream().map(MetaClassInstance::getId).collect(Collectors.toList());
            shape.getChildren().forEach(i -> {
                // 连接器不控制
                if (ShapeTypeEnum.EDGE.getName().equals(i.getShapeType())) {
                    return;
                }
                MetaClassInstance metaClassInstance = instanceMap.get(i.getModelId());
                if (metaClassInstance != null &&
                        (UMLDefinitionConstants.Property.equals(metaClassInstance.getClassifier().getId())
                                || UMLDefinitionConstants.Port.equals(metaClassInstance.getClassifier().getId()))
                        && (instanceIds.isEmpty() || !instanceIds.contains(i.getModelId()))) {
                    result.add(new CheckShapeDTO(i.getShapeId(), i.getModelId(), null));

                }
            });
        } else if (diagramInstance.getAppliedStereotypes() != null && (
                diagramInstance.getAppliedStereotypes().contains(UMLDefinitionConstants.SysMLBlockDefinitionDiagram)
                        || diagramInstance.getAppliedStereotypes().contains(UMLDefinitionConstants.SysMLPackageDiagram)
        )) {
            checkBlockInnerElements(projectId, shape, result);
        } else {
            // 其他图表校验
            log.info("checkInnerElements other than");
        }

        return result;
    }

    private static boolean isIbdOrPar(MetaClassInstance diagramInstance) {
        LogUtil.printSerializeOnlineLogs("diagramInstance: ", diagramInstance);
        return diagramInstance.getAppliedStereotypes() != null && (
                diagramInstance.getAppliedStereotypes().contains(UMLDefinitionConstants.SysMLInternalBlockDiagram)
                        || diagramInstance.getAppliedStereotypes().contains(UMLDefinitionConstants.SysMLParametricDiagram)
        );
    }

    private void checkBlockInnerElements(String projectId, CheckShapeDTO shape, List<CheckShapeDTO> result) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, shape: {}, result: {}", projectId, shape, result);
        List<CheckShapeDTO> blockShapes = getBlockShapeDTOS(projectId, shape);
        blockShapes.stream().filter(s -> StringUtils.isNotEmpty(s.getModelId()))
                .forEach(s -> {
                    final MetaClassInstance instance = internalUmlService.fetchExistInstance(s.getModelId(), projectId);
                    List<MetaClassInstance> allAttributes = getAllAttributes(projectId, instance);
                    List<String> instanceIds = allAttributes.stream().map(MetaClassInstance::getId).collect(Collectors.toList());
                    s.getChildren().forEach(i -> putCheckShapeDTO(projectId, result, instanceIds, i));
                });
    }

    private void putCheckShapeDTO(String projectId, List<CheckShapeDTO> result, List<String> instanceIds, CheckShapeDTO i) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, result: {}, instanceIds: {}, i: {}", projectId, result, instanceIds, i);
        if (StringUtils.isNotEmpty(i.getModelId())) {
            MetaClassInstance metaClassInstance = internalUmlService.fetchInstance(i.getModelId(), projectId);
            if (!(UMLDefinitionConstants.Property.equals(metaClassInstance.getMetaClass().getId())
                    || UMLDefinitionConstants.Port.equals(metaClassInstance.getMetaClass().getId()))) {
                return;
            }
            if (instanceIds.isEmpty() || !instanceIds.contains(i.getModelId())) {
                result.add(new CheckShapeDTO(i.getShapeId(), i.getModelId(), null));
            }
        } else {
            if (CollectionUtils.isEmpty(i.getChildren())) {
                return;
            }
            i.getChildren().forEach(c -> {
                MetaClassInstance metaClassInstance = internalUmlService.fetchInstance(c.getModelId(), projectId);
                if (UMLDefinitionConstants.Property.equals(metaClassInstance.getMetaClass().getId())
                        && (instanceIds.isEmpty() || !instanceIds.contains(c.getModelId()))) {
                    result.add(new CheckShapeDTO(c.getShapeId(), c.getModelId(), null));
                }
            });
        }
    }

    @NotNull
    private List<CheckShapeDTO> getBlockShapeDTOS(String projectId, CheckShapeDTO shape) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, shape: {}", projectId, shape);
        Queue<CheckShapeDTO> q = new LinkedList<>();
        List<CheckShapeDTO> blockShapes = new ArrayList<>();
        shape.getChildren().forEach(q::offer);
        while (!q.isEmpty()) {
            CheckShapeDTO poll = q.poll();
            if (ShapeTypeEnum.COMPARTMENT.getName().equals(poll.getShapeType()) || StringUtils.isEmpty(poll.getModelId())) {
                if (CollectionUtils.isNotEmpty(poll.getChildren())) {
                    poll.getChildren().forEach(q::offer);
                }
            } else {
                final MetaClassInstance instance = internalUmlService.fetchInstance(poll.getModelId(), projectId);
                if (instance == null) {
                    throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
                }
                if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.SysML_Block)) {
                    blockShapes.add(poll);
                } else {
                    if (poll.getChildren() != null && !poll.getChildren().isEmpty()) {
                        poll.getChildren().forEach(q::offer);
                    }
                }
            }
        }
        return blockShapes;
    }

    /**
     * 获取内部端口和部件属性
     *
     * @param projectId
     * @param instanceId
     * @return java.util.List<com.huawang.mdesign.model.service.vo.InnerElementVo>
     * @author baibf
     * @date 2022/09/16 10:14
     */
    @NotNull
    public List<InnerElementVo> queryInnerPortAndProperty(String projectId, String instanceId) {
        LogUtil.printOnlineLogs("queryInnerPortAndProperty -> projectId: {}, instanceId: {}", projectId, instanceId);
        final MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (instance == null) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }

        MetaClassInstance realInstance = getRealInstance(projectId, instance);
        Map<String, List<MetaClassInstance>> allAttributes = new HashMap<>();
        allAttributes.put(instance.getId(), getAllAttributes(projectId, realInstance));
        List<MetaClassInstance> results = getAddAttributes(projectId, allAttributes, instance, realInstance);
        return getInnerElementVos(projectId, realInstance, results);
    }

    @NotNull
    private List<InnerElementVo> getInnerElementVos(String projectId, MetaClassInstance realInstance, List<MetaClassInstance> results) {
        List<ModelPropertyInfo> resultModels = modelPropertyInfoService.createModelPropertyInfoList(projectId,
                results, Stream.of(UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.TypedElement_type)
                        .collect(Collectors.toList()));
        if (internalUmlService.checkInstanceType(projectId, realInstance,
                UMLDefinitionConstants.ReliabilityProfile_FMEAItem)) {
            resultModels =
                    resultModels.stream()
                            .filter(it -> it.checkInstanceType(UMLDefinitionConstants.ReliabilityProfile_Event))
                            .collect(Collectors.toList());
        }
        Map<String, ModelPropertyInfo> modelPropertyInfoMap = queryTypedElementTypeModelPropertyInfoMap(projectId, resultModels);

        List<InnerElementVo> innerElementVos = resultModels.stream().map(it -> makeInnerElement(projectId, it, modelPropertyInfoMap))
                .collect(Collectors.toList());
        // 只有拥有泛化关系才被认为是继承而来的
        List<MetaClassInstance> inheritedMemberInstances = internalUmlService.queryListInstanceProperty(projectId,
                realInstance, UMLDefinitionConstants.Classifier_inheritedMember);
        List<String> instanceIds = inheritedMemberInstances.stream().map(MetaClassInstance::getId)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(inheritedMemberInstances)) {
            innerElementVos.forEach(it -> {
                if (instanceIds.contains(it.getId())) {
                    it.setIsDisplay(true);
                }
            });

        }
        return innerElementVos;
    }

    private MetaClassInstance getRealInstance(String projectId, MetaClassInstance instance) {
        MetaClassInstance realInstance = instance;
        if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.Diagram)) {
            MetaClassInstance owner = internalUmlService.queryInstanceProperty(projectId, instance,
                    UMLDefinitionConstants.Element_owner);
            if (Objects.nonNull(owner)) {
                realInstance = owner;
            }
        }
        if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.StructuralFeature)) {
            MetaClassInstance type = internalUmlService.queryInstanceProperty(projectId, instance,
                    UMLDefinitionConstants.TypedElement_type);
            if (Objects.nonNull(type)) {
                realInstance = type;
            }
        }
        return realInstance;
    }

    public List<InnerElementTreeVo> batchQueryInnerPortAndProperty(QueryInnerPortAndPartPropertyDTO dto) {
        String projectId = dto.getProjectId();
        List<MetaClassInstance> results = new ArrayList<>();
        List<MetaClassInstance> instances = internalUmlService.fetchInstanceByIds(dto.getInstanceIds(), projectId);
        if (CollUtil.isEmpty(instances)) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        List<InnerElementTreeVo> innerElementTreeVos = Lists.newArrayList();

        Map<String, List<MetaClassInstance>> allAttributes = getAllAttributes(projectId, instances);
        for (MetaClassInstance instance : instances) {
            MetaClassInstance realInstance = getRealInstance(projectId, instance);
            List<MetaClassInstance> addAttributes = getAddAttributes(projectId, allAttributes, instance, realInstance);
            results.addAll(addAttributes);
            List<InnerElementVo> innerElementVos = getInnerElementVos(projectId, realInstance, results);
            InnerElementTreeVo treeVo = new InnerElementTreeVo();
            treeVo.setId(instance.getId());
            treeVo.setInnerElementVos(innerElementVos);
            innerElementTreeVos.add(treeVo);
        }
        return innerElementTreeVos;
    }

    private List<MetaClassInstance> getAddAttributes(String projectId, Map<String, List<MetaClassInstance>> allAttributes, MetaClassInstance instance, MetaClassInstance realInstance) {
        List<MetaClassInstance> addAttributes;
        if (internalUmlService.checkInstanceType(projectId, realInstance, UMLDefinitionConstants.Package)
                || internalUmlService.checkInstanceType(projectId, realInstance, UMLDefinitionConstants.Action)) {
            addAttributes = internalUmlService.queryListInstanceProperty(projectId, realInstance,
                    UMLDefinitionConstants.Element_ownedElement).stream().filter(it -> internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.StructuralFeature)).collect(Collectors.toList());
        } else if (internalUmlService.getGivenTypes(projectId, instance).contains(UMLDefinitionConstants.Simulation_ImageSwitcher)) {
            addAttributes = internalUmlService.queryListInstanceProperty(projectId, realInstance,
                    UMLDefinitionConstants.Class_nestedClassifier);
        } else {
            addAttributes = allAttributes.get(instance.getId());
        }
        return addAttributes;
    }

    /**
     * 查询模型TypedElement_type(类型)属性名称
     *
     * @param projectId
     * @param resultModels
     * @return
     */
    private Map<String, ModelPropertyInfo> queryTypedElementTypeModelPropertyInfoMap(String projectId, List<ModelPropertyInfo> resultModels) {
        //查询TypedElement_type（类型）属性的名称

        List<MetaClassInstance> typedElementTypeMetaClassInstances = resultModels.stream().map(e -> e.queryInstanceValue(UMLDefinitionConstants.TypedElement_type)).filter(Objects::nonNull).collect(Collectors.toList());

        return modelPropertyInfoService.createModelPropertyInfoMap(projectId, typedElementTypeMetaClassInstances, Collections.singletonList(UMLDefinitionConstants.NamedElement_name));
    }

    @NotNull
    private InnerElementVo makeInnerElement(final String projectId, final ModelPropertyInfo model, Map<String, ModelPropertyInfo> typedElementTypeNameMap) {
        LogUtil.printOnlineLogs("makeInnerElement -> projectId: ", projectId);
        final InnerElementVo innerElementVo = new InnerElementVo();

        String name = model.queryStringValue(UMLDefinitionConstants.NamedElement_name);

        innerElementVo.setName(name);
        innerElementVo.setId(model.getInstance().getId());

        final MetaClassInstance classInstance = model.getInstance();
        final ModelInfo info = internalUmlService.fetchModelInfoValue(projectId, classInstance);
        if (info != null) {
            innerElementVo.setIcon(internalModelIconService.queryIconByModelInfo(projectId, classInstance, info));
            // csm转换会存在没有图标的情况，此时设置为stereotype的图标
        } else {
            innerElementVo.setIcon(managerConfig.getModelInfoConfig().get(UMLDefinitionConstants.Stereotype).getIcon());
        }

        MetaClassInstance type = model.queryInstanceValue(UMLDefinitionConstants.TypedElement_type);
        // 判断内部端口和部件的时候，查找该模型的泛化链，查找该模型及父模型拥有的部件和端口
        List<MetaClassInstance> generalsCascadeList = new ArrayList<>();
        if (Objects.nonNull(type)) {
            generalsCascadeList = internalUmlService.findGeneralsCascade(projectId, type.getId(), true);
            //设置类型名称
            ModelPropertyInfo typedElementTypeModelPropertyInfo = typedElementTypeNameMap.get(type.getId());
            if (Objects.nonNull(typedElementTypeModelPropertyInfo)) {
                innerElementVo.setTypeName(typedElementTypeModelPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_name));
            }
        }
        if (CollectionUtils.isNotEmpty(generalsCascadeList)) {
            List<ModelPropertyInfo> models = modelPropertyInfoService.createModelPropertyInfoList(projectId,
                    generalsCascadeList, Stream.of(UMLDefinitionConstants.Classifier_attribute).collect(Collectors.toList()));
            boolean haveChild = models.stream().mapToLong(it ->
                    it.queryListInstanceValue(UMLDefinitionConstants.Classifier_attribute).size()).sum() != 0;
            innerElementVo.setHaveChild(haveChild);
        }

        final String distinguishProperty = getDistinguishProperty(model);
        if (distinguishProperty != null) {
            innerElementVo.setDistinguishProperty(distinguishProperty);
        }
        return innerElementVo;
    }

    @Nullable
    private static String getDistinguishProperty(@NotNull ModelPropertyInfo model) {
        LogUtil.printSerializeOnlineLogs("model: ", model);
        if (model.checkInstanceType(UMLDefinitionConstants.Customization_ValueProperty)) {
            return "ValueProperty";
        } else if (model.checkInstanceType(UMLDefinitionConstants.Customization_ConstraintProperty)) {
            return "ConstraintProperty";
        } else {
            return null;
        }
    }

    @NotNull
    private List<MetaClassInstance> getAllAttributes(String projectId,
                                                     @NotNull MetaClassInstance instance) {
        LogUtil.printSerializeOnlineLogs("getAllAttributes -> projectId: {}, instance: {}", projectId, instance);
        List<MetaClassInstance> parents = new ArrayList<>();
        if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.Classifier)) {
            parents = internalUmlService.findGeneralsCascade(projectId, instance.getId(), true);
        }

        final List<MetaClassInstance> attributes = internalUmlService.queryProperty(projectId, parents,
                UMLDefinitionConstants.Classifier_attribute);
        List<ModelPropertyInfo> attributeModels = modelPropertyInfoService.createModelPropertyInfoList(projectId,
                attributes,
                Stream.of(UMLDefinitionConstants.A_redefinedProperty_property_property,
                        UMLDefinitionConstants.Property_defaultValue).collect(Collectors.toList()));

        return attributeModels.stream().filter(it -> internalPropertyService.checkIsRedefineProperty(it, attributeModels))
                .map(ModelPropertyInfo::getInstance).collect(Collectors.toList());
    }

    @NotNull
    private Map<String, List<MetaClassInstance>> getAllAttributes(String projectId,
                                                                  @NotNull List<MetaClassInstance> instances) {
        LogUtil.printSerializeOnlineLogs("getAllAttributes -> projectId: {}, instance: {}", projectId, instances);
        List<MetaClassInstance> parents = new ArrayList<>();
        Map<String, List<String>> instanceMap = new HashMap<>();
        for (MetaClassInstance instance : instances) {
            if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.Classifier)) {
                List<MetaClassInstance> generalsCascade = internalUmlService.findGeneralsCascade(projectId, instance.getId(), true);
                parents.addAll(generalsCascade);
                instanceMap.put(instance.getUUID(), generalsCascade.stream().map(MetaClassInstance::getUUID).collect(Collectors.toList()));
            }
        }
        final List<MetaClassInstance> attributes = internalUmlService.queryProperty(projectId, parents, UMLDefinitionConstants.Classifier_attribute);
        List<ModelPropertyInfo> attributeModels = modelPropertyInfoService.createModelPropertyInfoList(projectId, attributes, Lists.newArrayList(UMLDefinitionConstants.A_redefinedProperty_property_property, UMLDefinitionConstants.Property_defaultValue));
        List<MetaClassInstance> metaClassInstances = attributeModels.stream()
                .filter(it -> internalPropertyService.checkIsRedefineProperty(it, attributeModels))
                .map(ModelPropertyInfo::getInstance).collect(Collectors.toList());
        Map<String, MetaClassInstance> metaClassInstanceMap = metaClassInstances.stream().collect(Collectors.toMap(MetaClassInstance::getUUID, e -> e));
        return instanceMap.keySet().stream().collect(Collectors.toMap(key -> key, key -> instanceMap.get(key).stream().map(metaClassInstanceMap::get).collect(Collectors.toList()), (a, b) -> b));
    }

    /**
     * 复制模型
     *
     * @param dto
     * @return com.huawang.mdesign.model.service.vo.CopyResultVo
     * @author xz
     * @date 2023/05/24 18:09
     */
    @NotNull
    public CopyResultVo paste(CopyDTO dto) {
        LogUtil.printSerializeOnlineLogs("paste -> dto: ", dto);
        final String projectId = dto.getProjectId();
        final String instanceId = dto.getInstanceId();
        final String targetInstanceId = dto.getTargetInstanceId();
        final String targetProjectId = dto.getTargetProjectId();
        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (instance == null) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }

        if (Objects.equals(projectId, targetProjectId) || StringUtils.isEmpty(targetProjectId)) {
            MetaClassInstance targetInstance = internalUmlService.fetchInstance(targetInstanceId, projectId);
            if (targetInstance == null) {
                throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
            }

            //判断是否可以容纳模型
            if (!internalOwnerService.validNodeCopyOwner(projectId, instance, targetInstance)) {
                throw AbortExecutionException.build(ErrorCode.INVALID_CONTAIN_MEMBER);
            }

            return pasteModel(projectId, instanceId, projectId, targetInstance);
        } else {
            MetaClassInstance targetInstance = internalUmlService.fetchInstance(targetInstanceId,
                    targetProjectId);
            if (targetInstance == null) {
                throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
            }

            //判断是否可以容纳模型
            if (!internalOwnerService.validNodeCopyToOtherOwner(projectId, targetProjectId, instance, targetInstance)) {
                throw AbortExecutionException.build(ErrorCode.INVALID_CONTAIN_MEMBER);
            }

            CopyResultVo copyResultVo = pasteModel(projectId, instanceId, targetProjectId, targetInstance);

            //判断粘贴元素中是否包含stereotype,如果包含则进行加载privateData。
            List<MetaClassInstance> addInstances =
                    this.internalUmlService.fetchInstanceByIds(new ArrayList<>(copyResultVo.getAddModel()), targetProjectId);
            List<MetaClassInstance> stereotypes = addInstances.stream().filter(it -> this.internalUmlService.getGivenTypes(projectId, it).contains(UMLDefinitionConstants.Stereotype))
                    .collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(stereotypes)) {
                Project project = projectManager.getValidProject(targetProjectId);
                this.initializeService.initialize(projectId, false, false, true, project.getProjectSpecification());
            }
            return copyResultVo;
        }
    }

    @NotNull
    private CopyResultVo pasteModel(String sourceProjectId, String sourceInstanceId, String targetProjectId,
                                    MetaClassInstance targetInstance) {
        LogUtil.printSerializeOnlineLogs("sourceProjectId: {}, sourceInstanceId: {}, targetProjectId: {}, targetInstance: {}",
                sourceProjectId, sourceInstanceId, targetProjectId, targetInstance);
        MetaClassInstance source = internalUmlService.fetchExistInstance(sourceInstanceId, sourceProjectId);

        CopyResultVo modelResultVo = new CopyResultVo();
        LocalTransaction transaction = transactionService.createTransaction(targetProjectId, COPY_MODEL);
        try {
            Map<String, MetaClassInstance> result = umlService.paste(sourceProjectId, sourceInstanceId, targetProjectId,
                    targetInstance.getId());
            // 粘贴出来的模型
            MetaClassInstance firstInstance = result.get(sourceInstanceId);
            if (firstInstance == null) {
                throw AbortExecutionException.build(ErrorCode.COPY_ERROR);
            }

            umlService.rename(targetProjectId, firstInstance);

            metaTypeConfigHandler(targetProjectId, result);

            // 复制粘贴后置处理
            pasteSupplement.pastePostProcessor(targetProjectId, firstInstance, targetInstance, result);
            // 粘贴后模型编号处理
            globalNumberGenerator.pasteElementSetNumber(sourceProjectId, targetProjectId, source, result);
            transactionService.commit(targetProjectId);
            InstanceVoUtils.fillCopyResultVo(modelResultVo, transaction, result);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(targetProjectId, transaction);
            throw AbortExecutionException.build(ErrorCode.COPY_ERROR, e);
        }

        return modelResultVo;
    }

    /**
     * 元类配置处理
     *
     * @param targetProjectId
     * @param result
     * @return void
     * @author xz
     * @date 2023/08/14 16:52
     */
    public void metaTypeConfigHandler(String targetProjectId, Map<String, MetaClassInstance> result) {
        LogUtil.printSerializeOnlineLogs("targetProjectId: {}, result: {}", targetProjectId, result);
        List<MetaClassInstance> metaTypeConfig =
                result.values().stream().filter(it -> this.internalUmlService.getGivenTypes(targetProjectId, it).contains(UMLDefinitionConstants.Customization_MetaTypeConfig))
                        .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(metaTypeConfig)) {
            return;
        }

        List<String> keys = Stream.of(UMLDefinitionConstants.Customization_MetaTypeConfig_diagramConfig,
                UMLDefinitionConstants.Customization_MetaTypeConfig_shapeMenuConfig).collect(Collectors.toList());
        Map<String, String> stereotypes = result.entrySet().stream()
                .filter(it -> this.internalUmlService.getGivenTypes(targetProjectId, it.getValue()).contains(UMLDefinitionConstants.Stereotype))
                .collect(Collectors.toMap(Map.Entry::getKey, it -> it.getValue().getId()));
        List<ModelPropertyInfo> diagramConfigs = modelPropertyInfoService.createModelPropertyInfoList(targetProjectId,
                metaTypeConfig, keys);
        List<UpdateModelDTO> updateModelDtos = new ArrayList<>();
        for (ModelPropertyInfo diagramConfig : diagramConfigs) {
            for (String key : keys) {
                String config = diagramConfig.queryStringValue(key);
                if (StringUtils.isNotEmpty(config)) {
                    for (Map.Entry<String, String> entry : stereotypes.entrySet()) {
                        if (entry.getValue() == null) {
                            return;
                        }

                        config = config.replaceAll(entry.getKey(), entry.getValue());
                    }

                    UpdateModelDTO newDto = new UpdateModelDTO();
                    newDto.setProjectId(targetProjectId);
                    newDto.setPropertyId(key);
                    newDto.setInstanceId(diagramConfig.getInstanceId());
                    newDto.setValue(config);
                    updateModelDtos.add(newDto);
                }
            }

        }

        if (CollectionUtils.isNotEmpty(updateModelDtos)) {
            umlService.updateModelByBatch(updateModelDtos);
        }

    }

    public void checkIn(ModelCheckInOutDTO dto) {
        LogUtil.printSerializeOnlineLogs("dto", dto);
        final String projectId = dto.getProjectId();
        List<MetaClassInstance> result = queryCheckInstanceList(dto, projectId);
        internalUmlService.setIsNotReadOnly(projectId, result.stream().map(BasicRElement::getId).collect(Collectors.toList()));
    }

    public void checkOut(ModelCheckInOutDTO dto) {
        LogUtil.printSerializeOnlineLogs("dto", dto);
        final String projectId = dto.getProjectId();
        List<MetaClassInstance> result = queryCheckInstanceList(dto, projectId);
        internalUmlService.setIsReadOnly(projectId, result.stream().map(BasicRElement::getId).collect(Collectors.toList()));
    }

    public void checkAll(ModelCheckDTO dto) {
        LogUtil.printSerializeOnlineLogs("dto", dto);
        final String projectId = dto.getProjectId();
        umlFacility.updateAllInstanceIsReadOnly(projectId, dto.getValue());
    }

    /**
     * 获取需要检入检出的模型列表
     *
     * @param dto
     * @param projectId
     * @return java.util.List<com.huawang.cmof.model.instances.MetaClassInstance>
     * @author xz
     * @date 2022/06/24 10:22
     */
    @NotNull
    private List<MetaClassInstance> queryCheckInstanceList(ModelCheckInOutDTO dto, String projectId) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, dto: {}", projectId, dto);
        List<MetaClassInstance> packages = internalUmlService.fetchInstanceByIds(dto.getIds(), projectId);
        if (CollectionUtils.isEmpty(packages)) {
            return Collections.emptyList();
        }

        List<MetaClassInstance> result = packages.stream().flatMap(p -> findCheckModel(projectId, p).stream())
                .collect(Collectors.toList());
        result.addAll(packages);
        return result;
    }

    @NotNull
    private List<MetaClassInstance> findCheckModel(String projectId, MetaClassInstance p) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, p: {}", projectId, p);
        List<MetaClassInstance> results = new ArrayList<>();
        List<MetaClassInstance> ownedElements = internalUmlService.getChildren(p, false,
                projectId).stream().filter(e ->
                !internalUmlService.checkInstanceType(projectId, e, UMLDefinitionConstants.Package)
        ).collect(Collectors.toList());
        results.addAll(ownedElements);
        results.addAll(ownedElements.stream().flatMap(it -> findCheckModel(projectId, it).stream()).collect(Collectors.toList()));
        return results;
    }

    /**
     * 获取自定义stereotype对应内置的基本类型
     *
     * @param projectId
     * @param stereotypeId
     * @return java.lang.String
     * @author xz
     * @date 2023/05/24 18:25
     */
    @Nullable
    public String queryMClassByStereotypeId(String projectId, String stereotypeId) {
        LogUtil.printOnlineLogs("projectId: {}, stereotypeId: {}", projectId, stereotypeId);
        return internalUmlService.queryMClassByStereotypeId(projectId, stereotypeId);
    }

    /**
     * 批量获取自定义stereotype对应内置的基本类型
     *
     * @param dto
     * @return java.util.List<com.huawang.mdesign.model.service.vo.MClassVo>
     * @author xz
     * @date 2023/05/24 18:25
     */
    @NotNull
    public List<MClassVo> queryMClassByStereotypeIds(QueryMClassDTO dto) {
        LogUtil.printSerializeOnlineLogs("queryMClassByStereotypeIds -> dto: ", dto);
        final String projectId = dto.getProjectId();
        List<MetaClassInstance> stereotypes = internalUmlService.fetchInstanceByIds(dto.getStereotypeIds(), projectId);
        if (CollectionUtils.isEmpty(stereotypes)) {
            return Collections.emptyList();
        }
        return stereotypes.stream().map(stereotype -> {
            MClassVo vo = new MClassVo();
            vo.setStereotypeId(stereotype.getId());
            String baseStereotype = internalUmlService.queryBaseStereotype(projectId, stereotype);
            if (StringUtils.isNotEmpty(baseStereotype)) {
                vo.setMclassId(baseStereotype);
                return vo;
            }

            List<String> metaClasses = internalUmlService.getSelfBasePropertyList(projectId, stereotype);
            if (CollectionUtils.isNotEmpty(metaClasses)) {
                vo.setMclassId(metaClasses.get(0));
            }

            return vo;
        }).collect(Collectors.toList());

    }

    @NotNull
    public List<CheckValidPropertyValueVo> checkModelIsTargetType(CheckValidModelTypeDTO dto) {
        LogUtil.printSerializeOnlineLogs("checkModelIsTargetType -> dto: ", dto);
        final String projectId = dto.getProjectId();
        Map<String, Set<String>> typeMap = internalUmlService.getGivenTypes(projectId,
                internalUmlService.fetchInstanceByIds(dto.getIds(), projectId));
        return dto.getIds().stream().map(id -> {
            CheckValidPropertyValueVo vo = new CheckValidPropertyValueVo();
            vo.setId(id);
            vo.setSelectable(typeMap.get(id).stream().anyMatch(it -> dto.getTypeIds().contains(it)));
            if (!StringUtils.equals(dto.getCheckMethod(), "") && (dto.getInstanceId().equals(id) || CollUtil.contains(dto.getInstanceIds(), id))) {
                vo.setSelectable(false);
            }
            return vo;
        }).collect(Collectors.toList());
    }

    @Nullable
    public String queryPropertyDataType(String projectId, String propertyName) {
        LogUtil.printOnlineLogs("projectId: {}, propertyName: {}", projectId, propertyName);
        return internalUmlService.queryPropertyDataType(projectId, propertyName);
    }

    @NotNull
    public List<String> queryChildDiagram(String projectId, String instanceId) {
        LogUtil.printOnlineLogs("queryChildDiagram -> projectId: {}, instanceId: {}", projectId, instanceId);
        MetaClassInstance classInstance = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(classInstance)) {
            log.warn(LogCodeConstants.WARN + "无法查询到模型实例{}", instanceId);
            return Collections.emptyList();
        }
        return internalDiagramService.queryChildDiagram(projectId, classInstance.getId());
    }

    public void updateReadOnly(UpdateReadOnlyDTO dto) {
        LogUtil.printSerializeOnlineLogs("updateReadOnly -> dto: ", dto);
        if (CollectionUtils.isEmpty(dto.getIds())) {
            return;
        }

        if (BooleanUtils.isTrue(dto.getReadonly())) {
            internalUmlService.setIsReadOnly(dto.getProjectId(), dto.getIds());
        } else {
            internalUmlService.setIsNotReadOnly(dto.getProjectId(), dto.getIds());
        }
    }

    @NotNull
    public List<ElementDisableVo> queryElementDisable(String projectId, List<String> instanceIds) {
        LogUtil.printOnlineLogs("queryElementDisable -> projectId: {}, instanceIds: {}", projectId, instanceIds);
        List<MetaClassInstance> instanceList = internalUmlService.fetchInstanceByIds(instanceIds, projectId);
        if (CollectionUtils.isEmpty(instanceList)) {
            return Collections.emptyList();
        }
        List<MetaClassInstance> unpackages = instanceList.stream().filter(i -> !internalUmlService.checkInstanceType(projectId, i, UMLDefinitionConstants.Package)).collect(Collectors.toList());

        Map<String, Boolean> packageMap = new HashMap<>();
        unpackages.forEach(i -> {
            List<MetaClassInstance> ancestor = internalUmlService.getAncestor(projectId, i);
            MetaClassInstance nestedPackage = ancestor.stream().filter(it ->
                    internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.Package)).findFirst().orElse(null);
            if (nestedPackage != null) {
                packageMap.put(i.getId(), nestedPackage.getIsReadOnly());
            } else {
                log.error("找不到上级包");
            }
        });

        return instanceList.stream().map(instance -> {
            ElementDisableVo elementDisableVo = new ElementDisableVo();
            elementDisableVo.setInstanceId(instance.getId());
            if (packageMap.containsKey(instance.getId())) {
                elementDisableVo.setIsDisable(packageMap.get(instance.getId()));
            } else {
                elementDisableVo.setIsDisable(instance.getIsReadOnly());
            }
            return elementDisableVo;
        }).collect(Collectors.toList());
    }

    @NotNull
    public Set<String> queryAllUserCreatedInstanceIds(String projectId) {
        LogUtil.printOnlineLogs("queryAllUserCreatedInstanceIds -> projectId: ", projectId);
        return internalUmlService.queryAllUserCreatedInstanceIds(projectId);
    }

    public List<InstanceVo> listSpecificInstanceByClassId(String projectId, List<String> classfierIds) {
        ConcurrentLinkedQueue<String> specificIds = new ConcurrentLinkedQueue<>();
        classfierIds
                .parallelStream()
                .forEach(classfierId -> specificIds.addAll(elementFindService.getMClassSpecificCascade(projectId, classfierId)));
        List<MetaClassInstance> metaClassInstances = iQueryModelService.queryInstanceByClassifierIds(projectId,
                specificIds
                        .parallelStream()
                        .collect(Collectors.toList()),
                true);
        return this.executorManager.executes(
                projectId,
                metaClassInstances,
                proceedingComputedStatuses ->
                        this.executorManager.getMakeInstanceVo(
                                projectId, proceedingComputedStatuses
                        ),
                InstanceVo.class
        );
    }

    public List<String> listSpecificPropertyKeyByClassId(String projectId, List<String> classfierIds) {
        ConcurrentLinkedQueue<String> specificIds = new ConcurrentLinkedQueue<>();
        classfierIds
                .parallelStream()
                .forEach(classfierId -> specificIds.addAll(elementFindService.getMClassSpecificCascade(projectId, classfierId)));
        return internalPropertyService.listStereoPropertyIds(projectId,
                specificIds
                        .parallelStream()
                        .collect(Collectors.toList()));

    }


    /**
     * 查询所有类型为typeIds的MetaClassInstance
     *
     * @param projectId
     * @param typeId
     * @return
     */
    public List<MetaClassInstance> querySpecifiedInstanceList(String projectId, String typeId) {
        return internalUmlService.querySpecifiedInstanceList(projectId, typeId);
    }

    /**
     * 查询所有类型为typeIds的MetaClassInstance
     *
     * @param projectId
     * @param typeId
     * @return
     */
    public List<SpecifiedInstanceVo> querySpecifiedVoList(String projectId, String typeId) {
        List<SpecifiedInstanceVo> vos = new ArrayList<>();
        List<MetaClassInstance> metaClassInstances = internalUmlService.querySpecifiedInstanceList(projectId, typeId);
        // 项目存在封装模型，查询不可见的模型数据
        List<String> encryptInstanceIds = encapsulationService.queryAllUnVisibleModelIds(projectId);
        for (MetaClassInstance i : metaClassInstances) {
            if (CollectionUtils.isNotEmpty(encryptInstanceIds) && encryptInstanceIds.contains(i.getId())) {
                continue;
            }
            SpecifiedInstanceVo vo = new SpecifiedInstanceVo();
            String name = elementNameService.fetchName(projectId, i);
            vo.setName(name);
            vo.setInstanceId(i.getId());
            vos.add(vo);
        }
        return vos;
    }

    @NotNull
    public KeyPairVo generateKeyPair() {
        KeyPairVo keyPairVo = new KeyPairVo();
        KeyPair keyPair;
        try {
            keyPair = RSAUtils.generateKeyPair();
        } catch (NoSuchAlgorithmException e) {
            log.error("密钥对生成失败", e);
            throw AbortExecutionException.build(ErrorCode.KEYPAIR_GENERATE_ERROR);
        }
        keyPairVo.setPublicKey(RSAUtils.convertKeyToString(keyPair.getPublic()));
        keyPairVo.setPrivateKey(RSAUtils.convertKeyToString(keyPair.getPrivate()));

        return keyPairVo;
    }

    @NotNull
    public String validExistEncryptModel(String projectId) {
        LogUtil.printOnlineLogs("validExistEncryptModel -> projectId: ", projectId);
        List<String> encryptInstanceIds = encapsulationService.queryAllEncryptInstanceIds(projectId);
        if (CollectionUtils.isNotEmpty(encryptInstanceIds)) {
            log.error("项目存在封装模型");
            throw AbortExecutionException.build(ErrorCode.CONTAIN_ENCRYPTEDMODEL_ERROR);
        }
        return BaseResponse.success().getMessage();
    }

    @NotNull
    public List<LackedModelVo> validModelIntergrity(String projectId, String instanceId) {
        LogUtil.printOnlineLogs("validModelIntergrity -> projectId: {}, instanceId: {}", projectId, instanceId);
        // 缺失模型可能存在根节点:modelService进行根节点过滤
        Project project = projectManager.getProject(projectId);
        if (Objects.isNull(project)) {
            log.error("项目查找失败");
            throw AbortExecutionException.build(ErrorCode.PROJECT_NOT_FOUND);
        }
        List<String> lackedModelIdList = encapsulationService.getReferenceElementIdsOutSide(projectId, instanceId)
                .stream().filter(it -> !StringUtils.equals(it, project.getRootModel()))
                .collect(Collectors.toList());

        // 校验模型是否与封装模型存在联系，存在则抛出异常
        validRelatedModel(projectId, instanceId, lackedModelIdList);
        if (CollectionUtils.isEmpty(lackedModelIdList)) {
            log.info("封装模型内均完整");
            return Collections.emptyList();
        }
        List<MetaClassInstance> lackedModelInstanceList = internalUmlService.fetchInstanceByIds(lackedModelIdList, projectId);
        Map<String, ModelPropertyInfo> lackedModelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(
                projectId,
                lackedModelInstanceList,
                Collections.singletonList(UMLDefinitionConstants.Element_owner));
        Map<MetaClassInstance, List<MetaClassInstance>> cascadeRouteMap = internalUmlService.getAncestor(projectId, lackedModelInstanceList);
        // 展示需要从根节点->缺失模型, 此处逆置List
        cascadeRouteMap.forEach((key, value) -> Collections.reverse(value));

        // 批量查询name和icon
        // 缺失模型Id
        Set<MetaClassInstance> allInstances = new HashSet<>();
        allInstances.addAll(lackedModelInstanceList);
        // 缺失模型ownerId
        allInstances.addAll(lackedModelPropertyInfoMap.values().stream().map(it ->
                        it.queryInstanceValue(UMLDefinitionConstants.Element_owner))
                .filter(Objects::nonNull)
                .collect(Collectors.toSet()));
        // 路径Ids
        allInstances.addAll(cascadeRouteMap.values().stream().flatMap(Collection::stream).collect(Collectors.toSet()));

        Map<String, String> iconMap = modelPropertyInfoService.queryIconBatch(projectId, new ArrayList<>(allInstances));
        Map<String, ModelPropertyInfo> allInstancesPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(
                projectId,
                new ArrayList<>(allInstances),
                Collections.singletonList(UMLDefinitionConstants.NamedElement_name));
        return lackedModelPropertyInfoMap.values().stream().map(it -> {
            MetaClassInstance lackedModel = it.getInstance();
            MetaClassInstance owner = it.queryInstanceValue(UMLDefinitionConstants.Element_owner);
            if (Objects.isNull(owner)) {
                log.error("模型所有者查找失败");
                throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
            }
            List<MetaClassInstance> cascadeRoute = cascadeRouteMap.get(lackedModel);
            if (CollectionUtils.isEmpty(cascadeRoute)) {
                log.error("模型祖先路径查找失败");
                throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
            }
            LackedModelVo lackedModelVo = new LackedModelVo();
            lackedModelVo.setInstance(
                    fillSelectElementItemByBatch(
                            Collections.singletonList(lackedModel.getId()),
                            allInstancesPropertyInfoMap,
                            iconMap).get(0));
            lackedModelVo.setOwner(
                    fillSelectElementItemByBatch(
                            Collections.singletonList(owner.getId()),
                            allInstancesPropertyInfoMap,
                            iconMap).get(0));
            lackedModelVo.setRoutes(
                    fillSelectElementItemByBatch(
                            cascadeRoute.stream().map(BasicRElement::getId).collect(Collectors.toList()),
                            allInstancesPropertyInfoMap,
                            iconMap));
            return lackedModelVo;
        }).collect(Collectors.toList());
    }

    /**
     * desciption:校验模型是否与封装、共享模型存在联系，存在则抛出异常
     */
    private void validRelatedModel(String projectId, String instanceId, List<String> lackedModelInstanceList) {
        final List<String> encryptIdList = encapsulationService.queryAllEncryptInstanceIds(projectId);
        final List<ShareHangLocation> sharedPackageList = modelUsageService.querySharingPackages(projectId);
        List<String> sharedPackageIdList = sharedPackageList.stream()
                .map(ShareHangLocation::getInstanceId)
                .collect(Collectors.toList());

        if (Boolean.TRUE.equals(internalUmlService.isTargetParent(projectId,
                encryptIdList,
                Collections.singletonList(instanceId)))) {
            log.error("已封装模型请勿再次封装");
            throw AbortExecutionException.build(ErrorCode.CONTAINED_BY_ENCRYPTEDMODEL_ERROR);
        }
        if (Boolean.TRUE.equals(internalUmlService.isTargetParent(projectId,
                Collections.singletonList(instanceId),
                encryptIdList))) {
            log.error("包含已封装模型，请勿再次封装");
            throw AbortExecutionException.build(ErrorCode.CONTAIN_ENCRYPTEDMODEL_ERROR);
        }
        if (Boolean.TRUE.equals(internalUmlService.isTargetParent(projectId,
                lackedModelInstanceList,
                Collections.singletonList(instanceId)))) {
            log.error("引用模型已被封装，当前模型无法被封装");
            throw AbortExecutionException.build(ErrorCode.REFERENCE_MODEL_CONTAINED_BY_ENCRYPTEDMODEL_ERROR);
        }
        if (Boolean.TRUE.equals(internalUmlService.isTargetParent(projectId,
                sharedPackageIdList,
                Collections.singletonList(instanceId)))) {
            log.error("在共享模型子节点下, 无法封装");
            throw AbortExecutionException.build(ErrorCode.ENCRYPT_SHARE_PACKAGE_ERROR);
        }
        if (Boolean.TRUE.equals(internalUmlService.isTargetParent(projectId,
                Collections.singletonList(instanceId),
                sharedPackageIdList))) {
            log.error("子节点包含共享模型，无法封装");
            throw AbortExecutionException.build(ErrorCode.ENCRYPT_SHARE_PACKAGE_ERROR);
        }
    }

    @NotNull
    private static List<SelectElementItem> fillSelectElementItemByBatch(List<String> instanceIds,
                                                                        Map<String, ModelPropertyInfo> modelPropertyInfoMap,
                                                                        Map<String, String> iconMap) {
        LogUtil.printSerializeOnlineLogs("instanceIds: ", instanceIds);
        return instanceIds.stream().map(it -> {
            ModelPropertyInfo modelPropertyInfo = modelPropertyInfoMap.get(it);
            SelectElementItem selectElementItem = new SelectElementItem();
            selectElementItem.setInstanceId(it);
            String name = modelPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_name);
            if (StringUtils.isEmpty(name)) {
                name = "   ";
            }
            selectElementItem.setName(name);
            selectElementItem.setIcon(iconMap.get(it));
            return selectElementItem;
        }).collect(Collectors.toList());
    }

    /**
     * description:封装模型，并隐藏其下选中的子节点
     */
    @NotNull
    public EncryptModelVo encryptModel(EncryptModelDTO dto) {
        LogUtil.printSerializeOnlineLogs("encryptModel -> dto: ", dto);
        final String projectId = dto.getProjectId();
        final String encryptModelId = dto.getEncryptModelId();
        final String stringPublickey = dto.getPublicKey();
        final List<Node> hiddenNodes = dto.getHiddenNodes();
        final List<Node> visibleNodes = dto.getVisibleNodes();
        final List<String> hiddenNodeIds = hiddenNodes.stream().map(Node::getId).collect(Collectors.toList());
        final List<String> visibleNodeIds = visibleNodes.stream().map(Node::getId).collect(Collectors.toList());
        Map<String, MetaClassInstance> hiddenNodeMap = internalUmlService.fetchInstances(hiddenNodeIds, projectId);
        Map<String, MetaClassInstance> visibleNodeMap = internalUmlService.fetchInstances(visibleNodeIds, projectId);
        Set<String> allHiddenModelIds = hiddenNodes.stream().flatMap(it -> {
            Boolean isLoaded = it.getLoaded();
            MetaClassInstance instance = hiddenNodeMap.get(it.getId());
            if (Objects.isNull(instance)) {
                log.error("模型查找失败");
                throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
            }
            if (BooleanUtils.isTrue(isLoaded)) {
                return Stream.of(instance.getId());
            } else {
                List<String> childrenCascade = internalUmlService.getChildrenCascadeIds(projectId, instance, true);
                return childrenCascade.stream().map(Objects::toString);
            }
        }).collect(Collectors.toSet());
        // 未被加载且未被勾选的子节点下默认全部隐藏
        visibleNodes.forEach(node -> {
            Boolean isLoaded = node.getLoaded();
            if (BooleanUtils.isTrue(isLoaded)) {
                return;
            }
            MetaClassInstance instance = visibleNodeMap.get(node.getId());
            if (Objects.isNull(instance)) {
                log.error("模型查找失败");
                throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
            }
            List<String> childrenCascade = internalUmlService.getChildrenCascadeIds(projectId, instance, false);
            allHiddenModelIds.addAll(childrenCascade.stream().map(Objects::toString).collect(Collectors.toSet()));
        });
        try {
            PublicKey publicKey = RSAUtils.convertStringToPublicKey(stringPublickey);
            String cipherText = RSAUtils.encryptData(encryptModelId, publicKey);
            // 模型封装
            encapsulationService.executeEncryptModelCommand(projectId, encryptModelId, cipherText,
                    new ArrayList<>(allHiddenModelIds));
        } catch (InvalidKeySpecException | RuntimeException e) {
            log.error("非法公钥", e);
            throw AbortExecutionException.build(ErrorCode.PUBLIC_KEY_ILLEGAL, e);
        } catch (Exception e) {
            throw AbortExecutionException.build(ErrorCode.ENCRYPT_MODEL_ERROR, e);
        }
        return fillEncryptModelVoInfo(projectId, encryptModelId);
    }

    @NotNull
    public EncryptModelVo decryptModel(DecryptModelDTO dto) {
        LogUtil.printSerializeOnlineLogs("decryptModel -> dto: ", dto);
        final String projectId = dto.getProjectId();
        final String encryptedModelId = dto.getEncryptedModelId();
        final String stringPrivatekey = dto.getPrivateKey();
        String cipherText = encapsulationService.queryCypherContext(projectId, encryptedModelId);
        try {
            PrivateKey privateKey = RSAUtils.convertStringToPrivateKey(stringPrivatekey);
            String decryptData = RSAUtils.decryptData(cipherText, privateKey);
            if (StringUtils.equals(encryptedModelId, decryptData)) {
                log.info("公钥密钥匹配，可以解封");
                // 模型解封
                encapsulationService.executeDecryptModelCommand(projectId, encryptedModelId);
            }
        } catch (InvalidKeySpecException | RuntimeException e) {
            log.error("非法私钥或私钥不匹配", e);
            throw AbortExecutionException.build(ErrorCode.PRIVATE_KEY_ERROR, e);
        } catch (Exception e) {
            log.error("私钥转化失败", e);
            throw AbortExecutionException.build(ErrorCode.KEYPAIR_GENERATE_ERROR, e);
        }
        return fillEncryptModelVoInfo(projectId, encryptedModelId);
    }

    @NotNull
    private EncryptModelVo fillEncryptModelVoInfo(String projectId,
                                                  String encryptModelId) {
        LogUtil.printOnlineLogs("projectId: {}, encryptModelId: {}", projectId, encryptModelId);
        if (Objects.isNull(encryptModelId)) {
            log.error("封装模型不存在");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        final List<String> childrenCascadeId = internalUmlService.getChildrenCascadeIds(projectId,
                Stream.of(encryptModelId).collect(Collectors.toList()), false);
        final List<MetaClassInstance> childrenCascade = this.internalUmlService.fetchInstanceByIds(childrenCascadeId, projectId)
                .stream().filter(BusinessJudgeService::isCreatedInteractive)
                .collect(Collectors.toList());
        final List<String> updateVisibleModelIds = childrenCascade.stream().map(BasicRElement::getId).collect(Collectors.toList());
        final Map<String, UnVisibleStatus> visibleStatusMap = encapsulationService.getUnVisibleModelStatus(projectId,
                updateVisibleModelIds);
        Boolean isEncrypted = encapsulationService.isEncryptModel(projectId, encryptModelId);
        EncryptModelVo encryptModelVo = new EncryptModelVo();
        // 变更模型的封装状态
        UpdateModelStatus updateModelEncryptStatus = new UpdateModelStatus();
        updateModelEncryptStatus.setId(encryptModelId);
        updateModelEncryptStatus.setIsEncrypted(isEncrypted);
        encryptModelVo.setUpdateEncryptModels(Collections.singletonList(updateModelEncryptStatus));
        // 变更模型的可见状态
        List<UpdateModelStatus> updateVisibleModels = updateVisibleModelIds.stream().map(it -> {
            UpdateModelStatus updateModelStatus = new UpdateModelStatus();
            updateModelStatus.setId(it);
            UnVisibleStatus status = visibleStatusMap.get(it);
            if (Objects.isNull(status)) {
                updateModelStatus.setHiddenStatus(2);
            } else {
                updateModelStatus.setHiddenStatus(status.getName());
            }
            return updateModelStatus;
        }).collect(Collectors.toList());
        encryptModelVo.setUpdateVisibleModels(updateVisibleModels);
        return encryptModelVo;
    }

    public static boolean isHideProperty(String id) {
        LogUtil.printOnlineLogs("id: ", id);
        return UMLDefinitionConstants.Customization_PartProperty.equals(id)
                || UMLDefinitionConstants.Customization_ValueProperty.equals(id)
                || UMLDefinitionConstants.SysML_FlowProperty.equals(id)
                || UMLDefinitionConstants.Customization_ConstraintProperty.equals(id)
                || UMLDefinitionConstants.Customization_ReferenceProperty.equals(id);
    }

    @NotNull
    private static List<String> getCustomizationKeywords(String projectId, ModelPropertyInfo model, List<ApplyStereotypeVo> stereotypeVos) {
        LogUtil.printSerializeOnlineLogs("getCustomizationKeywords -> projectId: {}, model: {}, stereotypeVos: {}", projectId,
                model, stereotypeVos);
        Map<String, Map<String, String>> projectKeywordsMap = KeywordsCache.getKeywordsMap();
        if (Objects.isNull(projectKeywordsMap) || !projectKeywordsMap.containsKey(projectId)) {
            return new ArrayList<>();
        }
        Map<String, String> stereotypeKeywordsMap = projectKeywordsMap.get(projectId);

        Map<String, String> stereotypeCnNameMap = stereotypeVos.stream().filter(it ->
                !isHideProperty(it.getId())).collect(Collectors.toMap(ApplyStereotypeVo::getId, ApplyStereotypeVo::getCnName));

        List<String> keywords = new ArrayList<>();
        List<MetaClassInstance> stereotypes = model.queryListInstanceValue(UMLDefinitionConstants.Element_appliedStereotype);
        boolean hasCustomizationKey = stereotypes.stream().anyMatch(it ->
                BusinessJudgeService.isCreatedInteractive(it) && stereotypeKeywordsMap.containsKey(it.getId()));
        for (MetaClassInstance stereotype : stereotypes) {
            final String keyword = getKeyword(stereotype, stereotypeKeywordsMap, stereotypeCnNameMap);
            if (keyword != null) {
                keywords.add(keyword);
            }
        }
        return hasCustomizationKey ? keywords : new ArrayList<>();
    }

    @Nullable
    private static String getKeyword(@NotNull MetaClassInstance stereotype,
                                     @NotNull Map<String, String> stereotypeKeywordsMap,
                                     @NotNull Map<String, String> stereotypeCnNameMap) {
        LogUtil.printSerializeOnlineLogs("stereotype: {}, stereotypeKeywordsMap: {}, stereotypeCnNameMap: {}",
                stereotype, stereotypeKeywordsMap, stereotypeCnNameMap);
        if (BusinessJudgeService.isCreatedInteractive(stereotype) && stereotypeKeywordsMap.containsKey(stereotype.getId())) {
            return stereotypeKeywordsMap.get(stereotype.getId());
        } else {
            return stereotypeCnNameMap.getOrDefault(stereotype.getId(), null);
        }
    }

    /**
     * 根据模型类型查询模型实例
     *
     * @param projectId
     * @param typeId
     * @return
     */
    @NotNull
    public List<SelectElementItem> queryInstanceByType(String projectId, String typeId) {
        List<MetaClassInstance> instances = internalUmlService.querySpecifiedInstanceList(projectId, typeId);
        List<SelectElementItem> items = new ArrayList<>(instances.size());
        QueryPropertyForm newqueryPropertyForm = internalUmlService.getQueryPropertyForm(instances,
                Stream.of(UMLDefinitionConstants.NamedElement_name).collect(Collectors.toList()));
        MofResultContainer mofResultContainer = internalUmlService.queryProperty(projectId, newqueryPropertyForm);
        instances.forEach(instance ->
                items.add(propertyService.createSelectElementItem(projectId, instance,
                        mofResultContainer.queryStringProperty(instance.getId(), UMLDefinitionConstants.NamedElement_name)))
        );
        return items;
    }


    /**
     * 查询模板项目模型数据
     *
     * @param dto
     * @return
     */
    @NotNull
    public List<MultiPropertyValueVo> queryTemplateProjectModel(QueryMultiPropertyValueDTO dto) {
        final String projectId = dto.getProjectId();
        List<MultiPropertyValueVo> result = new ArrayList<>();
        Map<String, MetaClassInstance> instanceMap = CollectionUtils.isNotEmpty(dto.getInstances()) ?
                this.internalUmlService.fetchInstances(
                        dto.getInstances().stream()
                                .map(QueryPropertyValueDTO::getInstanceId)
                                .collect(Collectors.toList()),
                        dto.getProjectId()
                ) : Collections.emptyMap();
        Set<String> propertyKeys = new HashSet<>();
        dto.getInstances().forEach(instance -> {
            if (instance.getKeys() != null) {
                propertyKeys.addAll(instance.getKeys());
            }
        });

        Map<String, Map<String, MofPropertyInfo>> instancesPropertyMap = internalUmlService.queryPropertyByModelKeyMap(projectId,
                instanceMap.values().stream().collect(Collectors.toMap(it -> it,
                        it -> new ArrayList<>(propertyKeys)))).getMofPropertyInfoMap();
        MultiPropertyValueVo propertyValueVo;
        Map<String, MofPropertyInfo> mofPropertyInfoMap;
        PropertyQueryParameter parameter;
        List<PropertyValueVo> values;
        for (QueryPropertyValueDTO modelPropertyDto : dto.getInstances()) {
            mofPropertyInfoMap = instancesPropertyMap.get(modelPropertyDto.getInstanceId());
            if (mofPropertyInfoMap == null || !instanceMap.containsKey(modelPropertyDto.getInstanceId())) {
                continue;
            }
            propertyValueVo = new MultiPropertyValueVo();
            propertyValueVo.setInstanceId(modelPropertyDto.getInstanceId());
            if (!mofPropertyInfoMap.isEmpty()) {
                values = new ArrayList<>(modelPropertyDto.getKeys().size());
                propertyValueVo.setProperties(values);
                for (Map.Entry<String, MofPropertyInfo> entry : mofPropertyInfoMap.entrySet()) {
                    if (modelPropertyDto.getKeys().contains(entry.getKey())) {
                        parameter = PropertyQueryParameter.builder()
                                .projectId(projectId)
                                .instance(instanceMap.get(modelPropertyDto.getInstanceId()))
                                .key(entry.getValue().getPropertyName())
                                .dataType(entry.getValue().getDataType())
                                .build();
                        values.add(getPropertyValue(parameter, entry.getValue()));
                    }
                }
            }
            result.add(propertyValueVo);
        }
        return result;
    }

    public List<MetaClassInstance> getMetaclassOrStereotype(QueryPropertyByTypeDTO dto) {
        LogUtil.printSerializeOnlineLogs("queryMultiGroupPropertyListByTypes -> dto: ", dto);
        final String projectId = dto.getProjectId();
        final List<String> metaclassOrStereotype = dto.getMetaclassOrStereotypeList();
        if (projectManager.getProject(projectId) == null) {
            log.info("项目文件不存在");
            return new ArrayList<>();
        }

        final List<MetaClassInstance> instances = internalUmlService.fetchInstanceByIds(metaclassOrStereotype, projectId);
        if (CollectionUtils.isEmpty(instances)) {
            log.info("元类模型查找失败，类型为{}", metaclassOrStereotype);
            return new ArrayList<>();
        }

        return instances;
    }

    public List<MultiGroupPropertyConfigVo> queryMultiGroupPropertyListByTypes(QueryPropertyByTypeDTO dto) {
        LogUtil.printSerializeOnlineLogs("queryMultiGroupPropertyListByTypes -> dto: ", dto);
        final String projectId = dto.getProjectId();
        List<MetaClassInstance> instances = getMetaclassOrStereotype(dto);
        if (CollectionUtils.isEmpty(instances)) {
            return Collections.emptyList();
        }
        List<MultiGroupPropertyConfigVo> result = new ArrayList<>();
        instances.forEach(it -> {
            Set<String> metaClassAndStereotypeIds = new HashSet<>();
            String metaClass = internalUmlService.isOnlyMetaClass(projectId, it) ?
                    it.getId() : internalUmlService.getSelfBasePropertyList(projectId, it).get(0);
            metaClassAndStereotypeIds.add(metaClass);

            // 查询元类属性
            final QueryOwnedPropertyForm form = QueryOwnedPropertyForm.builder()
                    .metaInstanceIds(Collections.singletonList(metaClass))
                    .findGeneralCascade(true)
                    .findSpecificCascade(false)
                    .needOppositeProperty(dto.getNeedOppositeProperty())
                    .excludeRedefinedProperty(BooleanUtils.isNotTrue(dto.getNeedReadOnlyProperty()))
                    .excludeReadOnlyProperty(BooleanUtils.isNotTrue(dto.getNeedReadOnlyProperty()))
                    .excludeComputedProperty(BooleanUtils.isNotTrue(dto.getNeedComputedProperty()))
                    .build();
            List<String> allPropertyIds = internalUmlService.getOwnedPropertiesByMetaInstanceIds(projectId, form);

            // 查询构造型属性
            if (!internalUmlService.isOnlyMetaClass(projectId, it)) {
                metaClassAndStereotypeIds.add(it.getId());
                List<String> stereotypePropertyIds = internalPropertyService.queryStereoProperties(projectId, Collections.singletonList(it));

                // 部分元素的部分属性并不需要要展示
                if (it.getId().equals(UMLDefinitionConstants.TableAndMatrix_DiagramTable)) {
                    stereotypePropertyIds.removeIf(e -> StringUtils.equals(e, UMLDefinitionConstants.TableAndMatrix_DiagramTable_rowElements)
                            || StringUtils.equals(e, UMLDefinitionConstants.TableAndMatrix_DiagramTable_columnIds)
                            || StringUtils.equals(e, UMLDefinitionConstants.TableAndMatrix_DiagramTable_rowsOrder));
                }
                if (it.getId().contains(UMLDefinitionConstants.SysML_ItemFlow)) {
                    stereotypePropertyIds.removeIf(e -> StringUtils.equals(e, UMLDefinitionConstants.SysML_ItemFlow_activities));
                }
                if (it.getId().equals(UMLDefinitionConstants.Customization_DataMapping)) {
                    stereotypePropertyIds.removeIf(e -> StringUtils.equals(e, UMLDefinitionConstants.Customization_DataMapping_mappingConfiguration));
                }
                allPropertyIds.addAll(stereotypePropertyIds);
            }
            allPropertyIds.removeIf(e -> e.equals(UMLDefinitionConstants.Abstraction_mapping));

            List<MetaClassInstance> allProperties = internalUmlService.fetchInstanceByIds(allPropertyIds, projectId);

            List<String> instanceIds = metaClassAndStereotypeIds.stream().flatMap(e -> this.iQueryDefinitionService.getGeneralsCascade(projectId, e, true).stream()).collect(Collectors.toList());

            //查询自定义属性
            List<MetaClassInstance> customizations = elementPropertyService.queryPropertyRelationInstanceBatch(projectId, new ArrayList<>(instanceIds),
                    UMLDefinitionConstants.Customization_Customization_customizationTarget);
            if (CollectionUtils.isNotEmpty(customizations)) {
                customizations.forEach(e -> {
                    List<MetaClassInstance> children = internalUmlService.getChildrenCascadeByClassifierIds(projectId, e,
                            Stream.of(UMLDefinitionConstants.CUSTOMIZATION_DERIVED_PROPERTY_SPECIFICATION).collect(Collectors.toList()), false);
                    allProperties.addAll(children);
                });
            }

            Set<String> specialHandlePropertySet = Stream.of(UMLDefinitionConstants.Namespace_ownedDiagram)
                    .collect(Collectors.toSet());
            allProperties.removeIf(e -> specialHandlePropertySet.contains(it.getId()));

            QueryPropertyForm queryPropertyForm = this.internalUmlService.getQueryPropertyForm(allProperties, Stream.of(UMLDefinitionConstants.TypedElement_type,
                    UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.StructuralFeature_isReadOnly).collect(Collectors.toList()));

            MofResultContainer mofResultContainer = this.internalUmlService.queryProperty(projectId, queryPropertyForm);

            List<PropertyConfig> infos = allProperties.stream().map(metaProperty -> {
                PropertyConfigDto propertyConfigDto = new PropertyConfigDto();
                propertyConfigDto.setKey(metaProperty.getId());
                propertyConfigDto.setStereotype(true);
                return initConfig(projectId, metaProperty, propertyConfigDto, instances.get(0), mofResultContainer);
            }).filter(Objects::nonNull).collect(Collectors.toList());

            propertyFixedOrderSort(infos);

            MultiGroupPropertyConfigVo multiGroupPropertyConfigVo = new MultiGroupPropertyConfigVo();
            String instanceId = it.getId();
            multiGroupPropertyConfigVo.setInstanceId(instanceId);
            List<PropertyConfigVO> propertyConfigVOs = new ArrayList<>(infos.size());
            infos.forEach(e -> {
                PropertyConfigVO propertyConfigVO = new PropertyConfigVO();
                BeanUtils.copyProperties(e, propertyConfigVO);
                propertyConfigVOs.add(propertyConfigVO);
            });
            multiGroupPropertyConfigVo.setProperties(propertyConfigVOs);
            result.add(multiGroupPropertyConfigVo);
        });

        return result;
    }


    public ModelResultVo batchAdd(BatchAddModelDTO dto) {
        LogUtil.printSerializeOnlineLogs("batchAdd: ", dto);
        final IModelOperation modelOperation = umlService.fetchModelOperation(dto.getMetaclass(), dto.getOperation());
        final String projectId = dto.getProjectId();
        final Project project = projectManager.getProject(projectId);
        if (Objects.isNull(project)) {
            throw AbortExecutionException.build(ErrorCode.PROJECT_NOT_FOUND);
        }

        ModelResultVo modelResultVo = new ModelResultVo();

        LocalTransaction transaction = transactionService.createTransaction(projectId, ADD_MODEL);
        try {
            modelResultVo.setAddModel(Sets.newHashSet());
            if (CollUtil.isNotEmpty(dto.getSources())) {
                for (String source : dto.getSources()) {
                    dto.setSource(source);
                    MetaClassInstance result = addModel(dto, modelOperation);
                    modelResultVo.getAddModel().add(result.getId());
                    InstanceVoUtils.fillAddModelResultVo(modelResultVo, transaction);
                }
            }
            if (CollUtil.isNotEmpty(dto.getParentIds())) {
                for (String parentId : dto.getParentIds()) {
                    dto.setParentId(parentId);
                    MetaClassInstance result = addModel(dto, modelOperation);
                    modelResultVo.getAddModel().add(result.getId());
                }
            }
            if (CollUtil.isNotEmpty(dto.getTargets())) {
                for (String target : dto.getTargets()) {
                    dto.setTarget(target);
                    MetaClassInstance result = addModel(dto, modelOperation);
                    modelResultVo.getAddModel().add(result.getId());
                    InstanceVoUtils.fillAddModelResultVo(modelResultVo, transaction);
                }
            }
            InstanceVoUtils.fillAddModelResultVo(modelResultVo, transaction);
            transactionService.commit(projectId);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.ADD_MODEL_ERROR, e);
        }
        return modelResultVo;
    }

    @NotNull
    public List<SelectAffectElementItem> queryAffectModelInfo(@NotNull String projectId, @NotNull String instanceId) {
        // 1.查询被影响元素属性，并过滤被替换元素子节点
        Set<String> generalizationType = Stream.of(
                UMLDefinitionConstants.Generalization_general, UMLDefinitionConstants.Generalization_specific).collect(Collectors.toSet());
        List<EncapsulationService.ReferenceInfo> referenceInfos = encapsulationService.getReferenceInfo(projectId, instanceId).stream()
                .map(it -> {
                    EncapsulationService.ReferenceInfo newReferenceInfo = new EncapsulationService.ReferenceInfo();
                    newReferenceInfo.setInstanceId(it.getInstanceId());
                    newReferenceInfo.setAffectPropertyKeys(it.getAffectPropertyKeys().stream()
                            .filter(key -> ! generalizationType.contains(key)).collect(Collectors.toList()));
                    return newReferenceInfo;
                }).collect(Collectors.toList());
        // 2.批量查询被影响元素属性值 -> 名称、Icon
        List<String> affectInstanceIds = referenceInfos.stream().map(it -> it.getInstanceId()).collect(Collectors.toList());
        Map<String, MetaClassInstance> affectInstanceMap = internalUmlService.fetchInstances(affectInstanceIds, projectId);
        QueryPropertyForm queryPropertyForm = new QueryPropertyForm();
        referenceInfos.forEach(referenceInfo ->
                queryPropertyForm.add(affectInstanceMap.get(referenceInfo.getInstanceId()), referenceInfo.getAffectPropertyKeys()));
        MofResultContainer affectPropertyContainer = internalUmlService.queryProperty(projectId, queryPropertyForm);
        List<MetaClassInstance> affectValues = affectPropertyContainer.values(queryPropertyForm).stream()
                .map(MetaClassInstance.class::cast).collect(Collectors.toList());
        List<MetaClassInstance> allInstances = Stream.concat(affectInstanceMap.values().stream(), affectValues.stream())
                .collect(Collectors.toList());

        // 3.查询icon
        Map<String, String> iconMap = modelPropertyInfoService.queryIconBatch(projectId, allInstances);
        // 4.查询名称
        MofResultContainer nameResultContainer = internalUmlService.getMofResultContainer(
                projectId, allInstances, UMLDefinitionConstants.NamedElement_name);
        // 5.查询只读
        Map<String, Boolean> isReadOnlyMap = businessJudgeService.isReadOnly(projectId, new ArrayList<>(affectInstanceMap.values()));
        // 6.查询属性key名称
        Map<String, PropertyConfig> propertyConfigs = managerConfig.getPropertyConfigs();

        return referenceInfos.stream().map(referenceInfo -> {
            final String affectInstanceId = referenceInfo.getInstanceId();
            List<AffectPropertyInfo> affectPropertyInfoList = referenceInfo.getAffectPropertyKeys().stream().map(
                    propertyKey -> {
                        AffectPropertyInfo affectPropertyInfo = new AffectPropertyInfo();
                        // 1.设置propertyKey
                        affectPropertyInfo.setPropertyKey(propertyKey);
                        // 2.设置propertyName
                        PropertyConfig propertyConfig = propertyConfigs.get(propertyKey);
                        if (propertyConfig != null) {
                            affectPropertyInfo.setPropertyName(propertyConfig.getName());
                        } else {
                            MetaClassInstance property = internalUmlService.fetchInstance(propertyKey, projectId);
                            affectPropertyInfo.setPropertyName(internalUmlService.queryStringProperty(
                                    projectId, property, UMLDefinitionConstants.NamedElement_name));
                        }
                        // 3.设置被影响属性属性值
                        List<MetaClassInstance> values = elementPropertyService.isMultiplicity(projectId, propertyKey) ?
                                affectPropertyContainer.queryListInstanceProperty(affectInstanceId, propertyKey) :
                                Collections.singletonList(affectPropertyContainer.queryInstanceProperty(affectInstanceId, propertyKey));
                        List<SelectAffectValueItem> selectAffectValueItemList = values.stream().map(value -> {
                            final String valueId = value.getId();
                            SelectAffectValueItem selectAffectValueItem = new SelectAffectValueItem();
                            // 1.设置是否为源元素
                            selectAffectValueItem.setSource(StringUtils.equals(valueId, instanceId));
                            // 2.填充id、name、icon
                            SelectElementItemUtil.fillSelectElementItem(selectAffectValueItem, valueId, iconMap, nameResultContainer);
                            return selectAffectValueItem;
                        }).collect(Collectors.toList());
                        affectPropertyInfo.setSelectAffectValueItemList(selectAffectValueItemList);
                        return affectPropertyInfo;
                    }).collect(Collectors.toList());
            SelectAffectElementItem selectAffectElementItem = new SelectAffectElementItem();
            // 1.填充是否只读
            selectAffectElementItem.setReadOnly(isReadOnlyMap.get(affectInstanceId));
            // 2.填充影响元素被影响属性
            selectAffectElementItem.setAffectPropertyInfoList(affectPropertyInfoList);
            // 2.填充id、name、icon
            SelectElementItemUtil.fillSelectElementItem(selectAffectElementItem, affectInstanceId, iconMap, nameResultContainer);
            return selectAffectElementItem;
        }).collect(Collectors.toList());
    }

    @NotNull
    public ModelResultVo replaceModel(@NotNull ReplaceModelDTO replaceModelDTO) {
        final String projectId = replaceModelDTO.getProjectId();
        MetaClassInstance sourceInstance = internalUmlService.fetchExistInstance(replaceModelDTO.getSourceInstanceId(), projectId);
        MetaClassInstance targetInstance = internalUmlService.fetchExistInstance(replaceModelDTO.getTargetInstanceId(), projectId);

        ModelResultVo modelResultVo = new ModelResultVo();
        LocalTransaction transaction = transactionService.createTransaction(projectId, UPDATE_MODEL);
        try {
            List<SelectAffectElementItem> selectAffectElementItems = replaceModelDTO.getSelectAffectElementItems();
            // 1.查询被影响属性的属性值
            List<String> fullIds = selectAffectElementItems.stream().flatMap(it -> {
                List<AffectPropertyInfo> affectPropertyInfoList = it.getAffectPropertyInfoList();
                String affectInstanceId = it.getInstanceId();
                List<String> affectValueIds = affectPropertyInfoList.stream().flatMap(affectPropertyInfo ->
                                affectPropertyInfo.getSelectAffectValueItemList().stream().map(SelectAffectValueItem::getInstanceId))
                        .collect(Collectors.toList());
                return Stream.concat(Stream.of(affectInstanceId), affectValueIds.stream());
            }).collect(Collectors.toList());
            Map<String, MetaClassInstance> instanceMap = internalUmlService.fetchInstances(fullIds, projectId);

            // 2.过滤属性(CSM仅会更新被替换模型子节点中 关系模型的引用属性)
            Set<String> skipInstanceIds = internalUmlService.getChildrenCascade(projectId, sourceInstance, true).stream()
                    .filter(it -> !internalUmlService.checkInstanceType(projectId, it, UMLDefinitionConstants.Relationship))
                    .map(BasicRElement::getId)
                    .collect(Collectors.toSet());
            List<SelectAffectElementItem> filteredAffectElementItems = selectAffectElementItems.stream()
                    .filter(it -> !skipInstanceIds.contains(it.getInstanceId()))
                    .collect(Collectors.toList());
            filteredAffectElementItems.forEach(it -> {
                final String instanceId = it.getInstanceId();
                List<AffectPropertyInfo> updatePropertyInfoList = it.getAffectPropertyInfoList().stream()
                        .filter(affectPropertyInfo -> {
                            final String propertyKey = affectPropertyInfo.getPropertyKey();
                            // 父节点的ownerProperty不需要更新
                            if (elementCheckService.isOwnerProperty(projectId, propertyKey) && sourceInstance.getOwnerId().equals(instanceId)) {
                                return false;
                            }
                            // 图例的指定属性不需要覆盖
                            if (UMLDefinitionConstants.Customization_LegendItem_SpecificElements.equals(propertyKey)) {
                                return false;
                            }
                            return true;
                        })
                        .collect(Collectors.toList());
                it.setAffectPropertyInfoList(updatePropertyInfoList);
            });
            List<UpdateModelDTO> updateModelDTOS = filteredAffectElementItems.stream().flatMap(it -> {
                final String instanceId = it.getInstanceId();
                return it.getAffectPropertyInfoList().stream()
                        .map(affectPropertyInfo -> {
                            final String propertyKey = affectPropertyInfo.getPropertyKey();
                            Object value;
                            // 如果属性值为*, 则对列表进行替换；否则直接替换
                            // 注:该业务边界值为仅更新属性值 不附带关联业务
                            if (elementPropertyService.isMultiplicity(projectId, propertyKey)) {
                                List<MetaClassInstance> originalValues = affectPropertyInfo.getSelectAffectValueItemList().stream()
                                        .map(SelectElementItem::getInstanceId)
                                        .map(instanceMap::get).collect(Collectors.toList());
                                if (originalValues.contains(targetInstance)) {
                                    originalValues.remove(sourceInstance);
                                } else {
                                    Collections.replaceAll(originalValues, sourceInstance, targetInstance);
                                }
                                value = originalValues;
                            } else {
                                value = targetInstance;
                            }
                            return UpdateModelFactory.newInstance(projectId, instanceId, propertyKey, value);
                        });
            }).collect(Collectors.toList());
            umlService.updateModelByBatch(updateModelDTOS);

            // 3.删除模型替换关联元素
            List<MetaClassInstance> affectInstances = selectAffectElementItems.stream().map(it ->
                    instanceMap.get(it.getInstanceId())).collect(Collectors.toList());
            deleteModelReplaceModels(projectId, affectInstances, sourceInstance);

            InstanceVoUtils.fillAddModelResultVo(modelResultVo, transaction);
            modelResultVo.getModifyModel().add(targetInstance.getId());
            transactionService.commit(projectId);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.UPDATE_MODEL_ERROR, e);
        }
        return modelResultVo;
    }

    public List<NamingRuleInfo> queryNamingRule(@NotBlank() String projectId,
                                                @NotBlank() String parentId) {
        MetaClassInstance parentInstance = internalUmlService.fetchInstance(parentId, projectId);
        if (ObjectUtil.isEmpty(parentInstance)) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        List<MetaClassInstance> namingRules = internalUmlService.querySpecifiedInstanceList(projectId, UMLDefinitionConstants.Customization_Extensions_NamingRule);

        List<MetaClassInstance> list = new ArrayList<>();
        list.addAll(namingRules);
        list.add(parentInstance);
        Map<String, ModelPropertyInfo> modelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, list, Collections.singletonList(UMLDefinitionConstants.NamedElement_qualifiedName));

        ModelPropertyInfo modelPropertyInfo = modelPropertyInfoMap.get(parentInstance.getId());
        String qualifiedName = modelPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_qualifiedName);
        if (StrUtil.isNotBlank(qualifiedName)) {
            qualifiedName += "::";
        }

        String finalQualifiedName = qualifiedName;
        namingRules = namingRules.stream().filter(temp -> modelPropertyInfoMap.containsKey(temp.getId()) && checkQualifiedName(finalQualifiedName, modelPropertyInfoMap.get(temp.getId()))).collect(Collectors.toList());

        Map<String, ModelPropertyInfo> namingPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, namingRules,
                Arrays.asList(UMLDefinitionConstants.Customization_Extensions_NamingRule_applyToElements,
                        UMLDefinitionConstants.Customization_Extensions_NamingRule_isNameUni,
                        UMLDefinitionConstants.Customization_Extensions_NamingRule_prefixRule,
                        UMLDefinitionConstants.Customization_Extensions_NamingRule_defaultName,
                        UMLDefinitionConstants.Customization_Extensions_NamingRule_separator,
                        UMLDefinitionConstants.NamedElement_name,
                        UMLDefinitionConstants.Customization_Extensions_NamingRule_prefix));

        return namingRules.stream().filter(temp -> namingPropertyInfoMap.containsKey(temp.getId())).map(namingRule -> {
            ModelPropertyInfo modelPropertyInfo1 = namingPropertyInfoMap.get(namingRule.getId());

            String prefixRule = null;
            MetaClassInstance metaClassInstance = modelPropertyInfo1.queryInstanceValue(UMLDefinitionConstants.Customization_Extensions_NamingRule_prefixRule);
            if (ObjectUtil.isNotEmpty(metaClassInstance)) {
                prefixRule = metaClassInstance.getId();
            }
            String s = modelPropertyInfo1.queryStringValue(UMLDefinitionConstants.NamedElement_name);
            NamingRuleInfo namingRuleInfo = new NamingRuleInfo();
            namingRuleInfo.setNameRuleId(namingRule.getId());
            namingRuleInfo.setDefaultName(modelPropertyInfo1.queryStringValue(UMLDefinitionConstants.Customization_Extensions_NamingRule_defaultName));
            namingRuleInfo.setSeparator(modelPropertyInfo1.queryStringValue(UMLDefinitionConstants.Customization_Extensions_NamingRule_separator));
            namingRuleInfo.setPrefix(modelPropertyInfo1.queryStringValue(UMLDefinitionConstants.Customization_Extensions_NamingRule_prefix));
            namingRuleInfo.setIsNameUni(modelPropertyInfo1.queryBooleanValue(UMLDefinitionConstants.Customization_Extensions_NamingRule_isNameUni));
            namingRuleInfo.setPrefixRule(prefixRule);
            namingRuleInfo.setName(s);
            namingRuleInfo.setApplyToElements(modelPropertyInfo1.queryListInstanceValue(UMLDefinitionConstants.Customization_Extensions_NamingRule_applyToElements).stream().map(MetaClassInstance::getId).collect(Collectors.toList()));
            return namingRuleInfo;
        }).collect(Collectors.toList());
    }

    /**
     * 确认全限定名称是否存在
     *
     * @param packageQualifiedName
     * @param modelPropertyInfo
     * @return
     */
    @NotNull
    private boolean checkQualifiedName(String packageQualifiedName,
                                       @Nullable ModelPropertyInfo modelPropertyInfo) {
        if (StrUtil.isNotBlank(packageQualifiedName) && modelPropertyInfo != null) {
            String qualifiedName = modelPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_qualifiedName);
            if (Objects.nonNull(qualifiedName)) {
                return qualifiedName.startsWith(packageQualifiedName);
            }
            return false;
        } else {
            //没有包内容说明是根节点
            return true;
        }
    }

    /**
     * @param projectId
     * @param affectInstances：被影响元素
     * @param sourceInstance：替换元素
     * @description:删除模型替换业务关联的模型
     * @author lx
     * @date 2025/3/11
     */
    private void deleteModelReplaceModels(@NotNull String projectId,
                                          @NotNull List<MetaClassInstance> affectInstances,
                                          @NotNull MetaClassInstance sourceInstance) {
        List<MetaClassInstance> deleteProperties = internalUmlService.getChildrenCascadeByClassifierIds(
                projectId, sourceInstance, Collections.singletonList(UMLDefinitionConstants.Property), true);

        List<String> relatedIds = new ArrayList<>();
        // 1.替换元素子节点(属性)的相反属性为被影响元素，则需删除被影响元素(属性)及关系连线
        if (CollectionUtils.isNotEmpty(deleteProperties)) {
            MofResultContainer mofResultContainer = internalUmlService.getMofResultContainer(
                    projectId, deleteProperties, UMLDefinitionConstants.Property_opposite);
            List<String> affectInstanceIds = affectInstances.stream().map(BasicRElement::getId).collect(Collectors.toList());
            List<String> relatedAssociationIds = deleteProperties.stream()
                    .filter(it -> {
                        MetaClassInstance oppositeProperty = mofResultContainer.queryInstanceProperty(it.getId(), UMLDefinitionConstants.Property_opposite);
                        return oppositeProperty != null && affectInstanceIds.contains(oppositeProperty.getId());
                    })
                    .flatMap(it -> Stream.of(it.getId(), it.getOwnerId()))
                    .collect(Collectors.toList());
            relatedIds.addAll(relatedAssociationIds);
        }
        // 2.删除影响元素中的特殊关系连线
        Set<String> specialRelationships = Stream.of(
                UMLDefinitionConstants.Transition,
                UMLDefinitionConstants.Message,
                UMLDefinitionConstants.Generalization).collect(Collectors.toSet());
        List<String> specialAffectIds = affectInstances.stream()
                .filter(it -> {
                    Set<String> givenTypes = internalUmlService.getGivenTypes(projectId, it);
                    return CollectionUtils.containsAny(givenTypes, specialRelationships);
                }).map(BasicRElement::getId)
                .collect(Collectors.toList());
        relatedIds.addAll(specialAffectIds);
        // 3.删除模型替换业务关联的模型元素；删除被替换模型关联的元素
        umlService.deleteModels(projectId, relatedIds);
        businessDeleteByIds(projectId, Collections.singletonList(sourceInstance.getId()));
    }

    public boolean checkInstanceTypes(CheckTypesDTO checkTypesDTO) {
        String projectId = checkTypesDTO.getProjectId();
        MetaClassInstance instance = internalUmlService.fetchInstance(checkTypesDTO.getInstanceId(), projectId);
        if (instance == null) {
            return false;
        }
        Set<String> givenTypes = internalUmlService.getGivenTypes(projectId, instance);
        List<String> typeIds = checkTypesDTO.getTypeIds();
        if (checkTypesDTO.getIsAndQuery()) {
            return givenTypes.containsAll(typeIds);
        }
        return typeIds.stream().anyMatch(givenTypes::contains);


    }

    /**
     * 属性合并预览
     *
     * @param propertyMergeDTO
     * @return
     */
    public List<PropertyMergePreviewVo> propertyMergePreview(PropertyMergeDTO propertyMergeDTO) {
        String projectId = propertyMergeDTO.getProjectId();
        MetaClassInstance sourceMetaClassInstance = internalUmlService.fetchInstance(propertyMergeDTO.getSourceInstanceId(), projectId);
        MetaClassInstance targetMetaClassInstance = internalUmlService.fetchInstance(propertyMergeDTO.getTargetInstanceId(), projectId);

        if (!iJudgeService.isGivenType(projectId, sourceMetaClassInstance, UMLDefinitionConstants.Class) ||
                !iJudgeService.isGivenType(projectId, targetMetaClassInstance, UMLDefinitionConstants.Class)) {
            throw AbortExecutionException.build(ErrorCode.NOT_CLASS_TYPED_INSTANCE);
        }


        List<String> needProperties = getNeedProperties(sourceMetaClassInstance, projectId);

        Map<String, MofPropertyInfo> sourcePropertyValueMap = internalUmlService.queryPropertyByKeys(projectId, sourceMetaClassInstance, needProperties);
        Map<String, MofPropertyInfo> targetPropertyValueMap = internalUmlService.queryPropertyByKeys(projectId, targetMetaClassInstance, needProperties);

        // 1.查询属性key名称
        Map<String, PropertyConfig> propertyConfigs = managerConfig.getPropertyConfigs();
        //2.查询属性多重性
        Map<String, Boolean> propertyKeyMultiplicityMap = internalUmlService.isMultiplicity(projectId, needProperties);


        List<PropertyMergePreviewVo> propertyMergePreviewVos = needProperties.stream().map(propertyKey -> {
            PropertyMergePreviewVo vo = new PropertyMergePreviewVo();
            String dataType = sourcePropertyValueMap.get(propertyKey).getDataType();
            vo.setPropertyKey(propertyKey);
            vo.setDataType(dataType);
            vo.setIsMultiplicity(propertyKeyMultiplicityMap.getOrDefault(propertyKey, Boolean.FALSE));
            // 2.设置propertyName
            PropertyConfig propertyConfig = propertyConfigs.get(propertyKey);
            if (propertyConfig != null) {
                vo.setPropertyName(propertyConfig.getName());
            } else {
                MetaClassInstance property = internalUmlService.fetchInstance(propertyKey, projectId);
                vo.setPropertyName(internalUmlService.queryStringProperty(
                        projectId, property, UMLDefinitionConstants.NamedElement_name));
            }
            return vo;
        }).collect(Collectors.toList());

        propertyMergePreviewVos.forEach(propertyMergePreviewVo -> {
            MofPropertyInfo sourceMofPropertyInfo = sourcePropertyValueMap.get(propertyMergePreviewVo.getPropertyKey());
            MofPropertyInfo targetMofPropertyInfo = targetPropertyValueMap.get(propertyMergePreviewVo.getPropertyKey());


            List<PreviewValue> beforePreviewValues = transferToPreviewValue(projectId, sourceMofPropertyInfo);
            propertyMergePreviewVo.setBeforeMergedValue(beforePreviewValues);

            List<PreviewValue> targetPreviewValues = transferToPreviewValue(projectId, targetMofPropertyInfo);
            propertyMergePreviewVo.setTargetPropertyValue(targetPreviewValues);


            List<PreviewValue> afterMergedValues = getAfterMergedValues(projectId, propertyMergeDTO.getSinglePropertyMergeRule(),
                    propertyMergeDTO.getOwnedPropertyMergeRule(), targetMetaClassInstance, propertyMergePreviewVo);

            //判断当前合并之后的属性是否需要更新
            boolean needUpdate;
            if (Objects.equals(propertyMergePreviewVo.getDataType(), TypeEnum.INSTANCE.getName())) {
                Map<String, com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> beforeValuesMap = beforePreviewValues.stream().map(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue.class::cast).
                        collect(Collectors.toMap(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getMetaClassInstanceId, Function.identity(), (k1, k2) -> k1));

                Map<String, com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> mergedValuesMap = afterMergedValues.stream().map(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue.class::cast).
                        collect(Collectors.toMap(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getMetaClassInstanceId, Function.identity(), (k1, k2) -> k1));
                needUpdate = !(beforeValuesMap.size() == mergedValuesMap.size() &&
                        beforeValuesMap.keySet().containsAll(mergedValuesMap.keySet()) && mergedValuesMap.values().stream().noneMatch(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getIsMerged));
            } else {
                Set<Object> beforeValues = beforePreviewValues.stream().map(Value::getVal).collect(Collectors.toSet());
                Set<Object> mergedValues = afterMergedValues.stream().map(Value::getVal).collect(Collectors.toSet());
                needUpdate = !(beforeValues.size() == mergedValues.size() && beforeValues.containsAll(mergedValues));
            }
            propertyMergePreviewVo.setNeedUpdate(needUpdate);
            propertyMergePreviewVo.setAfterMergedValue(afterMergedValues);

        });

        return getPropertyMergePreviewVos(propertyMergeDTO, propertyMergePreviewVos, projectId);
    }

    /**
     * 设置多重性
     *
     * @param propertyMergeDTO
     * @param propertyMergePreviewVos
     * @param projectId
     * @return
     */
    private List<PropertyMergePreviewVo> getPropertyMergePreviewVos(PropertyMergeDTO propertyMergeDTO, List<PropertyMergePreviewVo> propertyMergePreviewVos, String projectId) {
        List<String> metaClassInstanceIds = propertyMergePreviewVos.stream().map(e -> Stream.concat(e.getBeforeMergedValue().stream(), e.getTargetPropertyValue().stream()).collect(Collectors.toList())).flatMap(Collection::parallelStream).
                filter(e -> Objects.equals(e.getDataType(), TypeEnum.INSTANCE.getName())).map(e -> ((com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue) e).getMetaClassInstanceId()).distinct().collect(Collectors.toList());
        List<MetaClassInstance> metaClassInstances = internalUmlService.fetchInstanceByIds(metaClassInstanceIds, projectId);
        Map<String, ModelPropertyInfo> multiplicityModelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, metaClassInstances, Collections.singletonList(UMLDefinitionConstants.MultiplicityElement_multiplicity));
        List<PropertyMergePreviewVo> result = propertyMergePreviewVos.stream().filter(vo -> CollectionUtils.isNotEmpty(vo.getAfterMergedValue())).collect(Collectors.toList());

        result.stream().filter(e -> Objects.equals(e.getDataType(), TypeEnum.INSTANCE.getName())).forEach(e -> {
            e.getBeforeMergedValue().stream().map(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue.class::cast).forEach(beforeVo -> {
                String metaClassInstanceId = beforeVo.getMetaClassInstanceId();
                if (multiplicityModelPropertyInfoMap.containsKey(metaClassInstanceId)) {
                    beforeVo.setMultiplicity(multiplicityModelPropertyInfoMap.get(metaClassInstanceId).queryStringValue(UMLDefinitionConstants.MultiplicityElement_multiplicity));
                }
            });
            e.getTargetPropertyValue().stream().map(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue.class::cast).forEach(targetVo -> {
                String metaClassInstanceId = targetVo.getMetaClassInstanceId();
                if (multiplicityModelPropertyInfoMap.containsKey(metaClassInstanceId)) {
                    targetVo.setMultiplicity(multiplicityModelPropertyInfoMap.get(metaClassInstanceId).queryStringValue(UMLDefinitionConstants.MultiplicityElement_multiplicity));
                }
            });
            e.getAfterMergedValue().stream().map(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue.class::cast).forEach(mergedVo -> {
                String instanceId;
                if (Objects.equals(mergedVo.getIsMerged(), Boolean.TRUE)) {
                    instanceId = Objects.equals(propertyMergeDTO.getSinglePropertyMergeRule(), SinglePropertyMergeRuleEnum.REMAIN_SOURCE_PROPERTY_VALUE.getCode()) ?
                            mergedVo.getMetaClassInstanceId() : mergedVo.getMergedMetaClassInstanceId();
                } else {
                    instanceId = mergedVo.getMetaClassInstanceId();
                }
                mergedVo.setMultiplicity(multiplicityModelPropertyInfoMap.get(instanceId).queryStringValue(UMLDefinitionConstants.MultiplicityElement_multiplicity));
            });

        });
        return result;
    }

    /**
     * 获取需要的属性
     *
     * @param sourceMetaClassInstance 模型
     * @param projectId               项目id
     * @return
     */
    private List<String> getNeedProperties(MetaClassInstance sourceMetaClassInstance, String projectId) {
        List<String> typeList = Stream.concat(sourceMetaClassInstance.getAppliedStereotypes().stream(), Stream.of(sourceMetaClassInstance.getMetaClass().getId())).collect(Collectors.toList());
        return getNeedPropertiesByTypeIds(typeList, projectId);
    }

    public List<String> getNeedPropertiesByTypeIds(List<String> typeList, String projectId) {
        QueryOwnedPropertyForm queryOwnedPropertyForm = QueryOwnedPropertyForm.builder().metaInstanceIds(typeList).
                isFindBaseClass(true).findGeneralCascade(true).findSpecificCascade(false).needOppositeProperty(false).
                excludeRedefinedProperty(false).excludeReadOnlyProperty(false).excludeComputedProperty(false).
                isFindStereotypeProperties(true).isFindCustomizeProperties(true).isFindDerivedProperties(false).build();
        List<String> properties = internalUmlService.getOwnedPropertiesByInstanceId(projectId, queryOwnedPropertyForm).stream().
                filter(e -> (iJudgeService.isPropertyWritable(projectId, e) || PROPERTY_MERGE_NEED_COMPUTED_PROPERTIES.contains(e)) &&
                        !Objects.equals(e, UMLDefinitionConstants.SysML_AbstractRequirement_id)).collect(Collectors.toList());
        List<String> needProperties = new ArrayList<>();
        for (String property : properties) {
            boolean isNeedSkip = (iJudgeService.isComputedProperty(projectId, property) && !PROPERTY_MERGE_NEED_COMPUTED_PROPERTIES.contains(property)) ||
                    Objects.equals(UMLDefinitionConstants.Element_appliedStereotypeInstance, property);
            if (!isNeedSkip) {
                needProperties.add(property);
            }
        }
        return needProperties;
    }


    /**
     * 合并源属性根目标属性
     *
     * @param singlePropertyMergeRule
     * @param ownedPropertyMergeRule
     * @param
     */
    private List<PreviewValue> getAfterMergedValues(String projectId, Integer singlePropertyMergeRule,
                                                    Integer ownedPropertyMergeRule,
                                                    MetaClassInstance targetMetaClassInstance,
                                                    PropertyMergePreviewVo propertyMergePreviewVo) {

        List<PreviewValue> beforeMergedValue = propertyMergePreviewVo.getBeforeMergedValue();
        List<PreviewValue> targetPropertyValue = propertyMergePreviewVo.getTargetPropertyValue();
        if (CollectionUtils.isEmpty(beforeMergedValue) && CollectionUtils.isEmpty(targetPropertyValue)) {
            return Collections.emptyList();
        }
        boolean isMultiplicity = propertyMergePreviewVo.getIsMultiplicity();
        String propertyKey = propertyMergePreviewVo.getPropertyKey();

        String dataType = CollectionUtils.isNotEmpty(beforeMergedValue) ? beforeMergedValue.get(0).getDataType() : targetPropertyValue.get(0).getDataType();

        //基础属性合并
        if (!Objects.equals(dataType, TypeEnum.INSTANCE.getName())) {
            return mergeRawDataTypePropertyValue(singlePropertyMergeRule, isMultiplicity, beforeMergedValue, targetPropertyValue, propertyKey);

        }
        //多重性为1的模型属性走单一属性合并规则
        if (!isMultiplicity) {
            return mergedSingleInstancePropertyValue(projectId, singlePropertyMergeRule, targetMetaClassInstance, targetPropertyValue, beforeMergedValue);
        }

        //拥有属性/拥有操作/拥有接收
        Set<String> attributeSetNeedMerge = Stream.of(UMLDefinitionConstants.Class_ownedAttribute, UMLDefinitionConstants.Class_ownedOperation,
                UMLDefinitionConstants.Class_ownedReception).collect(Collectors.toSet());

        //构造型>对象
        Map<List<String>, List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue>> instanceBeforeValueMap = beforeMergedValue.stream().map(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue.class::cast).
                collect(Collectors.groupingBy(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getGivenTypes));

        Map<List<String>, List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue>> instanceTargetValueMap = targetPropertyValue.stream().map(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue.class::cast).
                collect(Collectors.groupingBy(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getGivenTypes));

        Map<List<String>, List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue>> needAddTargetValueMap = new HashMap<>();


        for (Map.Entry<List<String>, List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue>> targetEntry : instanceTargetValueMap.entrySet()) {
            List<String> stereotypes = targetEntry.getKey();
            List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> targetValues = targetEntry.getValue();
            if (!instanceBeforeValueMap.containsKey(stereotypes)) {
                needAddTargetValueMap.put(stereotypes, targetValues);
                continue;
            }
            //拥有属性/拥有操作/拥有接收三个属性支持相同属性合并，其它的属性都不走相同属性合并逻辑
            if (attributeSetNeedMerge.contains(propertyKey) && Objects.equals(ownedPropertyMergeRule, OwnedPropertyMergeRuleEnum.TYPE_AND_PROPERTY_NAME_MATCH_PROPERTY_MERGE.getCode())) {
                List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> beforeValues = instanceBeforeValueMap.get(stereotypes);

                Map<String, com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> beforeInstanceNameMap = beforeValues.stream().collect(Collectors.toMap(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getValue, Function.identity(), (k1, k2) -> k1));
                Map<String, com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> targetInstanceNameMap = targetValues.stream().collect(Collectors.toMap(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getValue, Function.identity(), (k1, k2) -> k1));

                //标记为需要合并状态，并且设置合并的模型id
                beforeValues.forEach(beforeValue -> {
                    com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue containsTargetValue = targetInstanceNameMap.get(beforeValue.getValue());
                    //类型都为空或者类型相同的时候需要合并
                    if (containsTargetValue != null && Objects.equals(containsTargetValue.getTypeId(), beforeValue.getTypeId())) {
                        beforeValue.setIsMerged(true);
                        beforeValue.setMergedMetaClassInstanceId(containsTargetValue.getMetaClassInstanceId());
                    }
                });

                List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> targetNotExistValues = targetValues.stream().filter(targetValue -> {
                    com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue containBeforeValue = beforeInstanceNameMap.get(targetValue.getValue());
                    return containBeforeValue == null || !Objects.equals(containBeforeValue.getTypeId(), targetValue.getTypeId());
                }).collect(Collectors.toList());

                needAddTargetValueMap.put(stereotypes, targetNotExistValues);
            } else {
                needAddTargetValueMap.put(stereotypes, targetValues);
            }
        }
        //设置需要copy标记
        needAddTargetValueMap.values().stream().flatMap(Collection::parallelStream).filter(e -> Objects.equals(e.getOwnerId(), targetMetaClassInstance.getId())).forEach(e -> e.setNeedCopy(true));

        return mergeMultiInstancePropertyValue(instanceBeforeValueMap, needAddTargetValueMap, instanceTargetValueMap);

    }

    /**
     * 合并多重性为*，dataType是Instnce类型的属性
     *
     * @param instanceBeforeValueMap
     * @param needAddTargetValueMap
     * @param instanceTargetValueMap
     * @return
     */
    private List<PreviewValue> mergeMultiInstancePropertyValue(Map<List<String>, List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue>> instanceBeforeValueMap,
                                                               Map<List<String>, List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue>> needAddTargetValueMap,
                                                               Map<List<String>, List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue>> instanceTargetValueMap) {
        List<PreviewValue> afterMergedValues = new ArrayList<>();
        for (Map.Entry<List<String>, List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue>> beforeEntry : instanceBeforeValueMap.entrySet()) {
            List<String> stereotypes = beforeEntry.getKey();
            List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> beforeValues = beforeEntry.getValue();
            Map<String, com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> nameVlueMap = beforeValues.stream().map(e -> {
                com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue newInstanceValue = new com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue();
                BeanUtils.copyProperties(e, newInstanceValue);
                return newInstanceValue;
            }).collect(Collectors.toMap(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getValue, Function.identity(), (k1, k2) -> k1));

            Set<String> beforeMetaInstanceIds = beforeValues.stream().map(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getMetaClassInstanceId).collect(Collectors.toSet());
            List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> needAddTargetValues = needAddTargetValueMap.getOrDefault(stereotypes, Collections.emptyList()).stream().
                    filter(e -> !beforeMetaInstanceIds.contains(e.getMetaClassInstanceId())).collect(Collectors.toList());
            List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> needUpdateNameInstanceValues = new ArrayList<>();
            needAddTargetValues.forEach(e -> {
                com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue newInstanceValue = new com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue();
                BeanUtils.copyProperties(e, newInstanceValue);
                if (nameVlueMap.containsKey(newInstanceValue.getValue())) {
                    needUpdateNameInstanceValues.add(newInstanceValue);
                } else {
                    nameVlueMap.put(newInstanceValue.getValue(), newInstanceValue);
                }
            });

            needUpdateNameInstanceValues.forEach(targetValue -> {
                int i = 1;
                com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue newInstanceValue = new com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue();
                BeanUtils.copyProperties(targetValue, newInstanceValue, "value");
                String tempStr = targetValue.getValue();
                newInstanceValue.setNeedUpdateName(Objects.equals(tempStr, targetValue.getValue()));
                while (nameVlueMap.containsKey(tempStr)) {
                    tempStr = targetValue.getValue() + i;
                    i++;
                }
                newInstanceValue.setValue(tempStr);
                nameVlueMap.put(tempStr, newInstanceValue);
            });
            afterMergedValues.addAll(nameVlueMap.values());
        }

        for (Map.Entry<List<String>, List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue>> targetEntry : instanceTargetValueMap.entrySet()) {
            if (!instanceBeforeValueMap.containsKey(targetEntry.getKey())) {
                List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> instancePreviewValues = targetEntry.getValue();
                afterMergedValues.addAll(previewValuesBeanCopy(instancePreviewValues));
            }
        }
        return afterMergedValues;
    }

    /**
     * 合并dataType是非Instance的属性
     *
     * @param singlePropertyMergeRule
     * @param isMultiplicity
     * @param beforeMergedValue
     * @param targetPropertyValue
     * @param propertyKey
     * @return
     */
    private List<PreviewValue> mergeRawDataTypePropertyValue(Integer singlePropertyMergeRule,
                                                             boolean isMultiplicity,
                                                             List<PreviewValue> beforeMergedValue,
                                                             List<PreviewValue> targetPropertyValue,
                                                             String propertyKey) {
        if (isMultiplicity) {
            Map<Object, PreviewValue> valueMap = Stream.concat(beforeMergedValue.stream(), targetPropertyValue.stream()).collect(Collectors.toMap(Value::getVal, Function.identity(), (k1, k2) -> k1));

            return previewValuesBeanCopy(valueMap.values());
        }
        List<PreviewValue> list = Objects.equals(singlePropertyMergeRule, SinglePropertyMergeRuleEnum.REMAIN_SOURCE_PROPERTY_VALUE.getCode()) ||
                Objects.equals(propertyKey, UMLDefinitionConstants.NamedElement_name) ? beforeMergedValue : targetPropertyValue;
        return previewValuesBeanCopy(list);
    }

    /**
     * bean copy
     *
     * @param values
     * @return
     */
    private List<PreviewValue> previewValuesBeanCopy(Collection<? extends PreviewValue> values) {
        return values.stream().map(e -> {
            PreviewValue previewValue;
            if (e instanceof RealPreviewValue) {
                previewValue = new RealPreviewValue();
            } else if (e instanceof com.huawang.mdesign.model.service.request.propertymerge.BooleanPreviewValue) {
                previewValue = new com.huawang.mdesign.model.service.request.propertymerge.BooleanPreviewValue();
            } else if (e instanceof com.huawang.mdesign.model.service.request.propertymerge.IntegerPreviewValue) {
                previewValue = new com.huawang.mdesign.model.service.request.propertymerge.IntegerPreviewValue();
            } else if (e instanceof com.huawang.mdesign.model.service.request.propertymerge.StringPreviewValue) {
                previewValue = new com.huawang.mdesign.model.service.request.propertymerge.StringPreviewValue();
            } else if (e instanceof com.huawang.mdesign.model.service.request.propertymerge.LongPreviewValue) {
                previewValue = new com.huawang.mdesign.model.service.request.propertymerge.LongPreviewValue();
            } else {
                previewValue = new com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue();
            }
            BeanUtils.copyProperties(e, previewValue);
            return previewValue;
        }).collect(Collectors.toList());
    }

    /**
     * 合并多重性为1的，dataType是Instance的属性
     *
     * @param projectId
     * @param singlePropertyMergeRule
     * @param targetMetaClassInstance
     * @param targetPropertyValue
     * @param beforeMergedValue
     * @return
     */
    private List<PreviewValue> mergedSingleInstancePropertyValue(String projectId,
                                                                 Integer singlePropertyMergeRule,
                                                                 MetaClassInstance targetMetaClassInstance,
                                                                 List<PreviewValue> targetPropertyValue,
                                                                 List<PreviewValue> beforeMergedValue) {

        if (Objects.equals(singlePropertyMergeRule, SinglePropertyMergeRuleEnum.REMAIN_SOURCE_PROPERTY_VALUE.getCode()) || CollectionUtils.isEmpty(targetPropertyValue)) {
            return previewValuesBeanCopy(beforeMergedValue);
        }
        com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue instancePreviewValue = (com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue) targetPropertyValue.get(0);
        if (CollectionUtils.isNotEmpty(beforeMergedValue)) {
            instancePreviewValue.setReplaceMetaClassInstanceId(((com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue) beforeMergedValue.get(0)).getMetaClassInstanceId());
        }
        if (Objects.equals(internalUmlService.fetchInstance(instancePreviewValue.getMetaClassInstanceId(), projectId).getOwnerId(), targetMetaClassInstance.getId())) {
            instancePreviewValue.setNeedCopy(true);
        }

        return previewValuesBeanCopy(targetPropertyValue);
    }

    public List<PreviewValue> transferToPreviewValue(String projectId, MofPropertyInfo mofPropertyInfo) {
        String dataType = mofPropertyInfo.getDataType();
        Object values = mofPropertyInfo.getValues();
        if (values == null) {
            return Collections.emptyList();
        }
        if (!Objects.equals(dataType, TypeEnum.INSTANCE.getName())) {
            return transferRawDataTypeValues(dataType, values);
        }

        List<MetaClassInstance> metaClassInstances = values instanceof List ? (List<MetaClassInstance>) values : Collections.singletonList((MetaClassInstance) values);
        Map<String, Set<String>> givenTypes = internalUmlService.getGivenTypes(projectId, metaClassInstances);
        Map<String, ModelPropertyInfo> modelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, metaClassInstances,
                Stream.of(UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.TypedElement_type, UMLDefinitionConstants.Reception_signal).collect(Collectors.toList()));
        Map<String, String> iconMap = modelPropertyInfoService.queryIconBatch(projectId, metaClassInstances);


        List<MetaClassInstance> typeInstances = modelPropertyInfoMap.values().stream().map(modelPropertyInfo -> {
            //拥有接收使用信号作为类型标记
            if (givenTypes.containsKey(UMLDefinitionConstants.Reception)) {
                return modelPropertyInfo.queryInstanceValue(UMLDefinitionConstants.Reception_signal);
            }
            return modelPropertyInfo.queryInstanceValue(UMLDefinitionConstants.TypedElement_type);
        }).filter(Objects::nonNull).collect(Collectors.toList());

        Map<String, ModelPropertyInfo> typePropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, typeInstances, Stream.of(UMLDefinitionConstants.NamedElement_name).collect(Collectors.toList()));


        return metaClassInstances.stream().map(metaClassInstance -> {
            com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue instancePreviewValue = new com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue();
            instancePreviewValue.setDataType(dataType);
            instancePreviewValue.setMetaClassInstanceId(metaClassInstance.getId());
            instancePreviewValue.setIcon(iconMap.get(metaClassInstance.getId()));
            MetaClassInstance typeInstance = modelPropertyInfoMap.get(metaClassInstance.getId()).queryInstanceValue(UMLDefinitionConstants.TypedElement_type);
            MetaClassInstance signalInstance = modelPropertyInfoMap.get(metaClassInstance.getId()).queryInstanceValue(UMLDefinitionConstants.Reception_signal);
            String typeId = "";
            String typeName = "";
            if (typeInstance != null) {
                typeId = typeInstance.getId();
                typeName = getTypeName(typeInstance, typePropertyInfoMap);
            }
            if (signalInstance != null) {
                typeId = signalInstance.getId();
                typeName = getTypeName(signalInstance, typePropertyInfoMap);
            }
            instancePreviewValue.setTypeId(typeId);
            instancePreviewValue.setOwnerId(metaClassInstance.getOwnerId());
            instancePreviewValue.setGivenTypes(givenTypes.getOrDefault(metaClassInstance.getId(), Collections.emptySet()).stream().sorted().collect(Collectors.toList()));
            instancePreviewValue.setMetaClassInstance(metaClassInstance);
            instancePreviewValue.setTypeName(typeName);
            String value = Optional.ofNullable(modelPropertyInfoMap.get(metaClassInstance.getId())).map(e -> e.queryStringValue(UMLDefinitionConstants.NamedElement_name)).orElse("");
            instancePreviewValue.setValue(value);
            return instancePreviewValue;
        }).collect(Collectors.toList());

    }

    private String getTypeName(MetaClassInstance typeInstance, Map<String, ModelPropertyInfo> typePropertyInfoMap) {
        if (typeInstance == null || typePropertyInfoMap.get(typeInstance.getId()) == null) {
            return "";
        }
        return typePropertyInfoMap.get(typeInstance.getId()).queryStringValue(UMLDefinitionConstants.NamedElement_name);
    }

    /**
     * 转换基础数据类型值
     *
     * @param dataType
     * @param values
     * @return
     */
    private List<PreviewValue> transferRawDataTypeValues(String dataType, Object values) {
        List<PreviewValue> result = Collections.emptyList();
        if (Objects.equals(dataType, TypeEnum.STRING.getName()) || Objects.equals(dataType, TypeEnum.UNLIMITEDNATURAL.getName())) {
            List<String> strValues = values instanceof List ? (List<String>) values : Collections.singletonList(values.toString());
            result = strValues.stream().map(strValue -> com.huawang.mdesign.model.service.request.propertymerge.StringPreviewValue.builder().dataType(dataType).value(strValue).build()).collect(Collectors.toList());
        } else if (Objects.equals(dataType, TypeEnum.BOOLEAN.getName())) {
            List<Boolean> boolValues = values instanceof List ? (List<Boolean>) values : Collections.singletonList((boolean) values);
            result = boolValues.stream().map(boolValue -> com.huawang.mdesign.model.service.request.propertymerge.BooleanPreviewValue.builder().dataType(dataType).value(boolValue).build()).collect(Collectors.toList());
        } else if (Objects.equals(dataType, TypeEnum.REAL.getName())) {
            List<Double> doubleValues = values instanceof List ? (List<Double>) values : Collections.singletonList((double) values);
            result = doubleValues.stream().map(doubleValue -> RealPreviewValue.builder().dataType(dataType).value(doubleValue).build()).collect(Collectors.toList());
        } else if (Objects.equals(dataType, TypeEnum.INTEGER.getName())) {
            List<Integer> intValues = values instanceof List ? ((List<Integer>) values) : Collections.singletonList((int) values);
            result = intValues.stream().map(intValue -> com.huawang.mdesign.model.service.request.propertymerge.IntegerPreviewValue.builder().dataType(dataType).value(intValue).build()).collect(Collectors.toList());
        } else if (Objects.equals(dataType, TypeEnum.LONG.getName())) {
            List<Long> longValues = values instanceof List ? (List<Long>) values : Collections.singletonList((long) values);
            result = longValues.stream().map(longValue -> com.huawang.mdesign.model.service.request.propertymerge.LongPreviewValue.builder().dataType(dataType).value(longValue).build()).collect(Collectors.toList());
        }
        return result;
    }

    /**
     * 执行模型合并
     *
     * @param propertyMergeDTO
     * @return
     */
    public CopyResultVo propertyMerge(PropertyMergeDTO propertyMergeDTO) {
        String projectId = propertyMergeDTO.getProjectId();
        String sourceInstanceId = propertyMergeDTO.getSourceInstanceId();

        List<PropertyMergePreviewVo> propertyMergePreviewVos = propertyMergeDTO.getPropertyMergePreviewVos().stream().filter(PropertyMergePreviewVo::getNeedUpdate).collect(Collectors.toList());
        CopyResultVo modelResultVo = new CopyResultVo();

        log.info("singlePropertyMergeRule:{},ownedPropertyMergeRule:{},propertyMerge:{}", propertyMergeDTO.getSinglePropertyMergeRule(), propertyMergeDTO.getOwnedPropertyMergeRule(), propertyMergePreviewVos);
        MetaClassInstance sourceMetaClassInstance = internalUmlService.fetchInstance(sourceInstanceId, projectId);

        List<PropertyMergePreviewVo> rawPropertyMergePreviewVos = propertyMergePreviewVos.stream().filter(e -> !Objects.equals(e.getDataType(), TypeEnum.INSTANCE.getName())).collect(Collectors.toList());
        List<PropertyMergePreviewVo> instancePropertyMergePreviewVos = propertyMergePreviewVos.stream().filter(e -> Objects.equals(e.getDataType(), TypeEnum.INSTANCE.getName())).collect(Collectors.toList());

        //更新模型
        List<UpdateModelDTO> updateModelDTOS = new ArrayList<>();
        List<ModifyPropertyDTO> modifyPropertyDTOS = new ArrayList<>();
        List<DeletePropertyDTO> deletePropertyDTOS = new ArrayList<>();
        Set<String> deleteModelIds = new HashSet<>();

        Map<String, MetaClassInstance> oldNewInstanceMap = new HashMap<>();
        List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> totalNeedMergedValues = new ArrayList<>();

        Set<String> totalNeedUpdatePropertyValues = new HashSet<>();

        LocalTransaction transaction = transactionService.createTransaction(projectId, UPDATE_MODEL);


        try {
            //处理基础数据类型属性
            for (PropertyMergePreviewVo rawPropertyMergePreviewVo : rawPropertyMergePreviewVos) {
                boolean isMultiplicity = rawPropertyMergePreviewVo.getIsMultiplicity();
                Object rawValue = isMultiplicity ? rawPropertyMergePreviewVo.getAfterMergedValue().stream().map(Value::getVal).collect(Collectors.toList()) :
                        rawPropertyMergePreviewVo.getAfterMergedValue().get(0).getVal();
                UpdateModelDTO rawPropertyValueUpdateModelDTO = UpdateModelFactory.newInstance(projectId, sourceInstanceId, rawPropertyMergePreviewVo.getPropertyKey(), rawValue);
                updateModelDTOS.add(rawPropertyValueUpdateModelDTO);
            }
            //处理Instance类型属性
            for (PropertyMergePreviewVo propertyMergePreviewVo : instancePropertyMergePreviewVos) {
                String propertyKey = propertyMergePreviewVo.getPropertyKey();
                List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> instancePropertyAfterMergedValue = propertyMergePreviewVo.getAfterMergedValue().stream().
                        map(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue.class::cast).collect(Collectors.toList());

                //源元素跟目标元素需要合并的属性值
                List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> needMergedValues = instancePropertyAfterMergedValue.stream().filter(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getIsMerged).collect(Collectors.toList());
                totalNeedMergedValues.addAll(needMergedValues);

                //目标元素需要复制到源元素的属性值
                List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> needCopyTargetValues = instancePropertyAfterMergedValue.stream().filter(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getNeedCopy).collect(Collectors.toList());
                copyTargetMetaClassInstances(needCopyTargetValues, projectId, sourceMetaClassInstance, oldNewInstanceMap);

                //如果存在需要根据目标元素属性进行复制一份的属性，那么用复制后的模型id代替
                List<String> newMetaClassInstanceIds = new ArrayList<>();
                List<String> removeMetaClassInstanceIds = new ArrayList<>();
                instancePropertyAfterMergedValue.forEach(e -> {
                    String metaClassInstanceId = e.getMetaClassInstanceId();
                    if (oldNewInstanceMap.containsKey(metaClassInstanceId)) {
                        removeMetaClassInstanceIds.add(metaClassInstanceId);
                        newMetaClassInstanceIds.add(oldNewInstanceMap.get(metaClassInstanceId).getId());
                    } else {
                        newMetaClassInstanceIds.add(metaClassInstanceId);
                    }
                });
                totalNeedUpdatePropertyValues.addAll(newMetaClassInstanceIds);

                List<String> replaceMetaClassInstanceIds = needCopyTargetValues.stream().map(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getReplaceMetaClassInstanceId).
                        filter(StringUtils::isNotBlank).collect(Collectors.toList());
                deleteModelIds.addAll(replaceMetaClassInstanceIds);

                List<MetaClassInstance> newMetaClassInstanceList = internalUmlService.fetchInstanceByIds(newMetaClassInstanceIds, projectId);
                boolean isMultiplicity = propertyMergePreviewVo.getIsMultiplicity();
                if (PROPERTY_MERGE_NEED_COMPUTED_PROPERTIES.contains(propertyKey)) {
                    ModifyPropertyDTO modifyPropertyDTO = new ModifyPropertyDTO();
                    modifyPropertyDTO.setInstanceId(sourceMetaClassInstance.getId());
                    modifyPropertyDTO.setProjectId(projectId);
                    modifyPropertyDTO.setDataType(propertyMergePreviewVo.getDataType());
                    modifyPropertyDTO.setKey(propertyKey);
                    modifyPropertyDTO.setValue(newMetaClassInstanceIds.stream().map(Object.class::cast).collect(Collectors.toList()));
                    modifyPropertyDTO.setIsMultiplicity(isMultiplicity);
                    modifyPropertyDTOS.add(modifyPropertyDTO);

                    removeMetaClassInstanceIds.forEach(deleteMetaClassInstanceId -> {
                        DeletePropertyDTO deletePropertyDTO = new DeletePropertyDTO();
                        deletePropertyDTO.setProjectId(projectId);
                        deletePropertyDTO.setInstanceId(sourceMetaClassInstance.getId());
                        deletePropertyDTO.setKey(propertyKey);
                        deletePropertyDTO.setDeleteInstanceId(deleteMetaClassInstanceId);
                        deletePropertyDTOS.add(deletePropertyDTO);
                    });

                } else {
                    Object values = isMultiplicity ? newMetaClassInstanceList : newMetaClassInstanceList.get(0);
                    UpdateModelDTO propertyUpdateModelDTO = UpdateModelFactory.newInstance(projectId, sourceInstanceId, propertyKey, values);
                    updateModelDTOS.add(propertyUpdateModelDTO);
                }
            }

            //创建合并属性的属性更新对象
            com.huawang.mdesign.model.service.request.propertymerge.InstancePropertyUpdateHolder instancePropertyUpdateHolder = createPropertyInstancePropertyUpdateHolderForPropertyMerge(projectId, propertyMergeDTO.getSinglePropertyMergeRule(), totalNeedMergedValues, oldNewInstanceMap);
            List<UpdateModelDTO> propertyInstanceInnerPropertiesUpdateDTOS = instancePropertyUpdateHolder.getUpdateModelDTOS();
            List<ModifyPropertyDTO> computedPropertyUpdateDTOS = instancePropertyUpdateHolder.getComputedPropertyUpdateDTOS();
            umlService.updateModelByBatch(propertyInstanceInnerPropertiesUpdateDTOS);
            computedPropertyUpdateDTOS.forEach(modifyPropertyDTO -> propertyManager.updatePropertyValue(modifyPropertyDTO));
            Set<String> firstLevelInstanceIds = new HashSet<>(totalNeedUpdatePropertyValues);

            totalNeedUpdatePropertyValues.addAll(oldNewInstanceMap.values().stream().map(MetaClassInstance::getId).collect(Collectors.toList()));
            totalNeedUpdatePropertyValues.removeIf(e -> Objects.equals(e, propertyMergeDTO.getTargetInstanceId()));

            //更新所有模型的Instance属性，完成对旧的元素的替换
            com.huawang.mdesign.model.service.request.propertymerge.InstancePropertyUpdateHolder propertyInstancePropertyUpdateHolderForNewInstances = createPropertyInstancePropertyUpdateHolderForNewInstances(totalNeedUpdatePropertyValues, projectId, oldNewInstanceMap);
            List<UpdateModelDTO> innerInstancePropertyUpdateModelDTOS = propertyInstancePropertyUpdateHolderForNewInstances.getUpdateModelDTOS();
            List<UpdateModelDTO> firstLevelInnerInstancePropertyUpdateModelDTOS = innerInstancePropertyUpdateModelDTOS.stream().filter(e ->
                    firstLevelInstanceIds.contains(e.getInstanceId())).collect(Collectors.toList());
            updateModelDTOS.addAll(firstLevelInnerInstancePropertyUpdateModelDTOS);

            List<UpdateModelDTO> notFirstLevelInnerInstancePropertyUpdateModelDTOS = innerInstancePropertyUpdateModelDTOS.stream().filter(e ->
                    !firstLevelInstanceIds.contains(e.getInstanceId())).collect(Collectors.toList());

            modifyPropertyDTOS.addAll(propertyInstancePropertyUpdateHolderForNewInstances.getComputedPropertyUpdateDTOS());
            deletePropertyDTOS.addAll(propertyInstancePropertyUpdateHolderForNewInstances.getDeletePropertyDTOS());

            //批量删除模型
            if (CollectionUtils.isNotEmpty(deleteModelIds)) {
                umlService.deleteModels(projectId, deleteModelIds);
            }
            //批量更新模型
            if (CollectionUtils.isNotEmpty(updateModelDTOS)) {
                umlService.updateModelByBatch(updateModelDTOS);
            }
            //更新非第一层属性模型属性
            updateNotFirstLevelInnerInstanceProperties(notFirstLevelInnerInstancePropertyUpdateModelDTOS);

            deletePropertyDTOS.forEach(deletePropertyDTO -> operations.commonRemoveProperty(deletePropertyDTO));

            modifyPropertyDTOS.forEach(modifyPropertyDTO -> propertyManager.updatePropertyValue(modifyPropertyDTO));


            transactionService.commit(projectId);
            InstanceVoUtils.fillCopyResultVo(modelResultVo, transaction, oldNewInstanceMap);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            final AbortExecutionException abortException = AbortExecutionException.build(ModelErrorCode.MERGE_ERROR.getCode(),
                    DisplayForm.build(ModelErrorCode.MERGE_ERROR.getMessage(),
                            new Object[]{e.getMessage()}),
                    DisplayForm.build(ModelErrorCode.MERGE_ERROR.getTitle()),
                    ModelErrorCode.MERGE_ERROR.getErrorLevelEnum());
            abortException.initCause(e);
            throw abortException;
        }


        return modelResultVo;
    }

    /**
     * 更新非第一层属性模型属性
     *
     * @param notFirstLevelInnerInstancePropertyUpdateModelDTOS
     */
    private void updateNotFirstLevelInnerInstanceProperties(List<UpdateModelDTO> notFirstLevelInnerInstancePropertyUpdateModelDTOS) {
        for (UpdateModelDTO notFirstLevelInnerInstancePropertyUpdateModelDTO : notFirstLevelInnerInstancePropertyUpdateModelDTOS) {
            try {
                umlService.updateModelByBatch(notFirstLevelInnerInstancePropertyUpdateModelDTO);
            } catch (RuntimeException exception) {
                log.error("执行" + notFirstLevelInnerInstancePropertyUpdateModelDTO.toString() + "报错", exception);
            }
        }
    }

    private com.huawang.mdesign.model.service.request.propertymerge.InstancePropertyUpdateHolder createPropertyInstancePropertyUpdateHolderForNewInstances(Set<String> totalNeedUpdatePropertyValues, String projectId, Map<String, MetaClassInstance> oldNewInstanceMap) {
        if (MapUtils.isEmpty(oldNewInstanceMap)) {
            return new com.huawang.mdesign.model.service.request.propertymerge.InstancePropertyUpdateHolder();
        }
        List<UpdateModelDTO> updateModelDTOS = new ArrayList<>();
        List<ModifyPropertyDTO> modifyPropertyDTOList = new ArrayList<>();
        List<DeletePropertyDTO> deletePropertyDTOS = new ArrayList<>();
        List<MetaClassInstance> needUpdatePropertyInstanceList = internalUmlService.fetchInstanceByIds(new ArrayList<>(totalNeedUpdatePropertyValues), projectId);
        List<MetaClassInstance> oldMetaClassInstances = internalUmlService.fetchInstanceByIds(new ArrayList<>(oldNewInstanceMap.keySet()), projectId);
        Map<String, MetaClassInstance> oldMetaClassInstancesMap = oldMetaClassInstances.stream().collect(Collectors.toMap(MetaClassInstance::getId, Function.identity(), (k1, k2) -> k1));

        Map<String, String> newOldInstanceIdMap = oldNewInstanceMap.entrySet().stream().collect(Collectors.toMap(entry -> entry.getValue().getId(), Map.Entry::getKey, (k1, k2) -> k1));
        Map<List<String>, List<String>> typePropertiesMap = new HashMap<>();
        for (MetaClassInstance needUpdatePropertyInstance : needUpdatePropertyInstanceList) {
            List<String> typeIdList = Stream.concat(needUpdatePropertyInstance.getAppliedStereotypes().stream(), Stream.of(needUpdatePropertyInstance.getMetaClass().getId())).sorted().collect(Collectors.toList());
            List<String> needProperties = typePropertiesMap.getOrDefault(typeIdList, getNeedPropertiesByTypeIds(typeIdList, projectId)).stream().filter(e -> {
                String dataType = internalUmlService.queryPropertyDataType(projectId, e);
                return Objects.equals(dataType, TypeEnum.INSTANCE.getName());
            }).collect(Collectors.toList());

            typePropertiesMap.putIfAbsent(typeIdList, needProperties);
            //查询属性多重性
            Map<String, Boolean> propertyKeyMultiplicityMap = internalUmlService.isMultiplicity(projectId, needProperties);

            Map<String, MofPropertyInfo> oldPropertyValueMap = Collections.emptyMap();
            String oldId = newOldInstanceIdMap.get(needUpdatePropertyInstance.getId());
            if (oldId != null && oldMetaClassInstancesMap.containsKey(oldId)) {
                oldPropertyValueMap = internalUmlService.queryPropertyByKeys(projectId, oldMetaClassInstancesMap.get(oldId), needProperties);
            }
            Map<String, MofPropertyInfo> propertyValueMap = internalUmlService.queryPropertyByKeys(projectId, needUpdatePropertyInstance, needProperties);

            for (String needProperty : needProperties) {
                MofPropertyInfo mofPropertyInfo = propertyValueMap.get(needProperty);
                MofPropertyInfo oldMofPropertyInfo = oldPropertyValueMap.get(needProperty);

                boolean isMultiplicity = propertyKeyMultiplicityMap.get(needProperty);
                Object values = getValues(needProperty, oldMofPropertyInfo, mofPropertyInfo);

                if (isNeedSkip(values)) {
                    continue;
                }

                List<MetaClassInstance> metaClassInstances = isMultiplicity ? ((List<MetaClassInstance>) values) : Collections.singletonList((MetaClassInstance) values);

                List<MetaClassInstance> newMetaClassInstances = metaClassInstances.stream().map(metaClassInstance ->
                        oldNewInstanceMap.getOrDefault(metaClassInstance.getId(), metaClassInstance)).collect(Collectors.toList());
                Set<String> newMetaClassInstanceIds = newMetaClassInstances.stream().map(MetaClassInstance::getId).collect(Collectors.toSet());


                if (PROPERTY_MERGE_NEED_COMPUTED_PROPERTIES.contains(needProperty)) {
                    List<Object> needModifyMetaClassInstanceIds = newMetaClassInstances.stream().map(e -> (Object) e.getId()).collect(Collectors.toList());
                    ModifyPropertyDTO modifyPropertyDTO = new ModifyPropertyDTO();
                    modifyPropertyDTO.setInstanceId(needUpdatePropertyInstance.getId());
                    modifyPropertyDTO.setProjectId(projectId);
                    modifyPropertyDTO.setDataType(TypeEnum.INSTANCE.getName());
                    modifyPropertyDTO.setKey(needProperty);
                    modifyPropertyDTO.setValue(needModifyMetaClassInstanceIds);
                    modifyPropertyDTO.setIsMultiplicity(isMultiplicity);
                    modifyPropertyDTOList.add(modifyPropertyDTO);
                } else if (metaClassInstances.stream().anyMatch(e -> !newMetaClassInstanceIds.contains(e.getId()))) {

                    Object updateValue = isMultiplicity ? newMetaClassInstances : newMetaClassInstances.get(0);
                    UpdateModelDTO updateModelDTO = UpdateModelFactory.newInstance(projectId, needUpdatePropertyInstance.getId(), needProperty, updateValue);
                    updateModelDTOS.add(updateModelDTO);
                }
            }
        }
        return new com.huawang.mdesign.model.service.request.propertymerge.InstancePropertyUpdateHolder(updateModelDTOS, modifyPropertyDTOList, deletePropertyDTOS);
    }

    private Object getValues(String needProperty, MofPropertyInfo oldMofPropertyInfo, MofPropertyInfo mofPropertyInfo) {
        Object values;
        if (PROPERTY_MERGE_NEED_COMPUTED_PROPERTIES.contains(needProperty)) {
            values = Objects.nonNull(oldMofPropertyInfo) ? oldMofPropertyInfo.getValues() : null;
        } else {
            values = Objects.nonNull(mofPropertyInfo) ? mofPropertyInfo.getValues() : null;
        }
        return values;
    }

    private boolean isNeedSkip(Object values) {
        return values == null || ((values instanceof List) && CollectionUtils.isEmpty((List<MetaClassInstance>) values));
    }

    /**
     * 执行复制模型操作，复制后的模型如果有修改名称的需求，也需要对其名称进行修改
     *
     * @param needCopyTargetValues
     * @param projectId
     * @param sourceMetaClassInstance
     */
    private void copyTargetMetaClassInstances(List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> needCopyTargetValues, String projectId, MetaClassInstance sourceMetaClassInstance, Map<String, MetaClassInstance> oldNewInstanceMap) {
        List<String> instanceIds = needCopyTargetValues.stream().map(com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue::getMetaClassInstanceId).collect(Collectors.toList());
        List<MetaClassInstance> metaClassInstances = internalUmlService.fetchInstanceByIds(instanceIds, projectId);
        Map<String, Set<String>> givenTypes = internalUmlService.getGivenTypes(projectId, metaClassInstances);
        List<MetaClassInstance> diagramInstances = metaClassInstances.stream().filter(metaClassInstance -> {
            Set<String> set = givenTypes.getOrDefault(metaClassInstance.getId(), Collections.emptySet());
            return set.contains(UMLDefinitionConstants.UMLDiagram) ||
                    set.contains(UMLDefinitionConstants.Diagram);
        }).collect(Collectors.toList());

        Map<String, ModelPropertyInfo> modelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, diagramInstances, Collections.singletonList(UMLDefinitionConstants.Diagram_context));

        for (com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue needCopyTargetValue : needCopyTargetValues) {
            String needCopyTargetValueMetaClassInstanceId = needCopyTargetValue.getMetaClassInstanceId();

            if (oldNewInstanceMap.containsKey(needCopyTargetValueMetaClassInstanceId)) {
                continue;
            }
            //执行复制操作
            MetaClassInstance source = internalUmlService.fetchInstance(needCopyTargetValueMetaClassInstanceId, projectId);

            Map<String, MetaClassInstance> result = umlService.paste(projectId, needCopyTargetValueMetaClassInstanceId, projectId, sourceMetaClassInstance.getId());
            // 粘贴出来的模型
            MetaClassInstance firstInstance = result.get(needCopyTargetValueMetaClassInstanceId);
            if (firstInstance == null) {
                throw AbortExecutionException.build(ErrorCode.COPY_ERROR);
            }
            boolean needUpdateName = needCopyTargetValue.getNeedUpdateName();
            //如果存在名称重复修改了名称的情况，这里复制出来的新模型需要更新名称
            if (needUpdateName) {
                umlService.updateModel(projectId, firstInstance.getId(), UMLDefinitionConstants.NamedElement_name, needCopyTargetValue.getValue());
            }
            //如果是非用户创建来源的模型，修改其复制生成的模型标记为用户创建
            if (!iJudgeService.isCreatedInteractive(source)) {
                List<String> newInstanceIds = result.values().stream().map(MetaClassInstance::getId).collect(Collectors.toList());
                elementStateService.updateProfileModelCreatorType(projectId, newInstanceIds, ModelCreatorType.CREATE_INTERACTIVE);
            }

            //如果图形的上下文不为空，那么进行替换
            if (modelPropertyInfoMap.containsKey(needCopyTargetValueMetaClassInstanceId)) {
                MetaClassInstance diagramContext = modelPropertyInfoMap.get(needCopyTargetValueMetaClassInstanceId).queryInstanceValue(UMLDefinitionConstants.Diagram_context);
                if (diagramContext != null) {
                    umlService.updateModel(projectId, firstInstance.getId(), UMLDefinitionConstants.Diagram_context, sourceMetaClassInstance);
                }

            }

            metaTypeConfigHandler(projectId, result);

            // 复制粘贴后置处理
            pasteSupplement.pastePostProcessor(projectId, firstInstance, sourceMetaClassInstance, result);
            // 粘贴后模型编号处理
            globalNumberGenerator.pasteElementSetNumber(projectId, projectId, source, result);


            oldNewInstanceMap.putAll(result);


        }

    }

    //需要合并的属性的属性进行合并操作
    private com.huawang.mdesign.model.service.request.propertymerge.InstancePropertyUpdateHolder createPropertyInstancePropertyUpdateHolderForPropertyMerge(String projectId,
                                                                                                                                                            Integer singlePropertyMergeRule,
                                                                                                                                                            List<com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue> needMergedValues,
                                                                                                                                                            Map<String, MetaClassInstance> oldNewInstanceMap) {
        List<UpdateModelDTO> updateModelDTOS = new ArrayList<>();
        List<ModifyPropertyDTO> modifyPropertyDTOList = new ArrayList<>();
        Map<List<String>, List<String>> typePropertiesMap = new HashMap<>();
        for (com.huawang.mdesign.model.service.request.propertymerge.InstancePreviewValue needMergedValue : needMergedValues) {
            MetaClassInstance source = internalUmlService.fetchInstance(needMergedValue.getMetaClassInstanceId(), projectId);
            MetaClassInstance target = internalUmlService.fetchInstance(needMergedValue.getMergedMetaClassInstanceId(), projectId);
            List<String> typeIdList = Stream.concat(source.getAppliedStereotypes().stream(), Stream.of(source.getMetaClass().getId())).sorted().collect(Collectors.toList());
            List<String> needProperties = typePropertiesMap.containsKey(typeIdList) ? typePropertiesMap.get(typeIdList) : getNeedPropertiesByTypeIds(typeIdList, projectId);
            typePropertiesMap.putIfAbsent(typeIdList, needProperties);

            Map<String, MofPropertyInfo> sourcePropertyValueMap = internalUmlService.queryPropertyByKeys(projectId, source, needProperties);
            Map<String, MofPropertyInfo> targetPropertyValueMap = internalUmlService.queryPropertyByKeys(projectId, target, needProperties);

            //2.查询属性多重性
            Map<String, Boolean> propertyKeyMultiplicityMap = internalUmlService.isMultiplicity(projectId, needProperties);

            //更新属性的属性
            for (String needProperty : needProperties) {
                MofPropertyInfo sourceMofPropertyInfo = sourcePropertyValueMap.get(needProperty);
                MofPropertyInfo targetMofPropertyInfo = targetPropertyValueMap.get(needProperty);
                String innerDataType = sourceMofPropertyInfo.getDataType();

                Object value;
                Object sourceValues = sourceMofPropertyInfo.getValues();
                Object targetValues = targetMofPropertyInfo.getValues();
                Boolean propertyMultiplicity = propertyKeyMultiplicityMap.get(needProperty);

                if (Objects.equals(propertyMultiplicity, Boolean.TRUE)) {
                    value = getMergedMultiPropertyValues(innerDataType, sourceValues, targetValues, oldNewInstanceMap);
                } else {
                    value = getMergedSinglePropertyValues(singlePropertyMergeRule, innerDataType, sourceValues, targetValues);
                }

                if (value != null) {
                    if (Objects.equals(innerDataType, TypeEnum.INSTANCE.getName()) && PROPERTY_MERGE_NEED_COMPUTED_PROPERTIES.contains(needProperty)) {
                        List<Object> metaClassInstanceIds = new ArrayList<>();
                        if (value instanceof List) {
                            List<MetaClassInstance> temp = (List<MetaClassInstance>) value;
                            metaClassInstanceIds.addAll(temp.stream().map(MetaClassInstance::getId).collect(Collectors.toList()));
                        } else {
                            metaClassInstanceIds.add(((MetaClassInstance) value).getId());
                        }
                        ModifyPropertyDTO modifyPropertyDTO = new ModifyPropertyDTO();
                        modifyPropertyDTO.setInstanceId(needMergedValue.getMetaClassInstanceId());
                        modifyPropertyDTO.setProjectId(projectId);
                        modifyPropertyDTO.setDataType(innerDataType);
                        modifyPropertyDTO.setKey(needProperty);
                        modifyPropertyDTO.setValue(metaClassInstanceIds);
                        modifyPropertyDTO.setIsMultiplicity(propertyMultiplicity);
                        modifyPropertyDTOList.add(modifyPropertyDTO);
                    } else {
                        UpdateModelDTO updateModelDTO = UpdateModelFactory.newInstance(projectId, source.getId(), needProperty, value);
                        updateModelDTOS.add(updateModelDTO);
                    }
                }
            }
        }
        return new com.huawang.mdesign.model.service.request.propertymerge.InstancePropertyUpdateHolder(updateModelDTOS, modifyPropertyDTOList, null);
    }

    private @Nullable Object getMergedMultiPropertyValues(String innerDataType, Object sourceValues, Object targetValues, Map<String, MetaClassInstance> oldNewInstanceMap) {
        Object value;
        boolean isSourceEqualsMerged;
        if (Objects.equals(innerDataType, TypeEnum.STRING.getName()) ||
                Objects.equals(innerDataType, TypeEnum.UNLIMITEDNATURAL.getName())) {
            Set<String> strSourceValues = ((List<String>) sourceValues).stream().collect(Collectors.toSet());
            List<String> mergedStrValues = Stream.concat(strSourceValues.stream(), ((List<String>) targetValues).stream()).distinct().collect(Collectors.toList());
            value = mergedStrValues;
            isSourceEqualsMerged = strSourceValues.size() == mergedStrValues.size() && strSourceValues.containsAll(mergedStrValues);
        } else if (Objects.equals(innerDataType, TypeEnum.INTEGER.getName())) {
            Set<Integer> intSourceValues = ((List<Integer>) sourceValues).stream().collect(Collectors.toSet());
            List<Integer> mergedIntValues = Stream.concat(intSourceValues.stream(), ((List<Integer>) targetValues).stream()).distinct().collect(Collectors.toList());
            value = mergedIntValues;
            isSourceEqualsMerged = intSourceValues.size() == mergedIntValues.size() && intSourceValues.containsAll(mergedIntValues);
        } else if (Objects.equals(innerDataType, TypeEnum.REAL.getName())) {
            Set<Double> doubleSourceValues = ((List<Double>) sourceValues).stream().collect(Collectors.toSet());
            List<Double> mergedDoubleValues = Stream.concat(doubleSourceValues.stream(), ((List<Double>) targetValues).stream()).distinct().collect(Collectors.toList());
            value = mergedDoubleValues;
            isSourceEqualsMerged = doubleSourceValues.size() == mergedDoubleValues.size() && doubleSourceValues.containsAll(mergedDoubleValues);
        } else if (Objects.equals(innerDataType, TypeEnum.LONG.getName())) {
            Set<Long> longSourceValues = ((List<Long>) sourceValues).stream().collect(Collectors.toSet());
            List<Long> mergedLongValues = Stream.concat(longSourceValues.stream(), ((List<Long>) targetValues).stream()).distinct().collect(Collectors.toList());
            value = mergedLongValues;
            isSourceEqualsMerged = longSourceValues.size() == mergedLongValues.size() && longSourceValues.containsAll(mergedLongValues);
        } else if (Objects.equals(innerDataType, TypeEnum.BOOLEAN.getName())) {
            Set<Boolean> boolSourceValues = ((List<Boolean>) sourceValues).stream().collect(Collectors.toSet());
            List<Boolean> mergedBoolValues = Stream.concat(((List<Boolean>) sourceValues).stream(), ((List<Boolean>) targetValues).stream()).distinct().collect(Collectors.toList());
            value = mergedBoolValues;
            isSourceEqualsMerged = boolSourceValues.size() == mergedBoolValues.size() && boolSourceValues.containsAll(mergedBoolValues);
        } else {
            List<MetaClassInstance> sourceMetaClassInstances = (List<MetaClassInstance>) sourceValues;
            List<MetaClassInstance> targetMetaClassInstances = (List<MetaClassInstance>) targetValues;
            Map<String, MetaClassInstance> metaClassInstanceMap = Stream.concat(sourceMetaClassInstances.stream(),
                    targetMetaClassInstances.stream()).collect(Collectors.toMap(MetaClassInstance::getId, Function.identity(), (k1, k2) -> k1));
            List<MetaClassInstance> mergedInstanceValues = metaClassInstanceMap.entrySet().stream().map(entry -> {
                if (oldNewInstanceMap.containsKey(entry.getKey())) {
                    return oldNewInstanceMap.get(entry.getKey());
                } else {
                    return entry.getValue();
                }
            }).collect(Collectors.toList());
            value = mergedInstanceValues;
            Set<String> sourceMetaClassInstanceIds = sourceMetaClassInstances.stream().map(MetaClassInstance::getId).collect(Collectors.toSet());
            Set<String> mergedMetaClassInstanceIds = mergedInstanceValues.stream().map(MetaClassInstance::getId).collect(Collectors.toSet());
            isSourceEqualsMerged = sourceMetaClassInstanceIds.size() == mergedMetaClassInstanceIds.size() && sourceMetaClassInstanceIds.containsAll(mergedMetaClassInstanceIds);
        }

        return isSourceEqualsMerged ? null : value;
    }

    private @Nullable Object getMergedSinglePropertyValues(Integer singlePropertyMergeRule, Object innerDataType, Object sourceValues, Object targetValues) {
        Object value;
        boolean isSourceEqualsMerged;
        if (targetValues == null || Objects.equals(singlePropertyMergeRule, SinglePropertyMergeRuleEnum.REMAIN_SOURCE_PROPERTY_VALUE.getCode())) {
            value = sourceValues;
            isSourceEqualsMerged = true;
        } else {
            value = targetValues;
            if (Objects.equals(innerDataType, TypeEnum.INSTANCE.getName())) {
                isSourceEqualsMerged = sourceValues != null && Objects.equals(((MetaClassInstance) sourceValues).getId(), ((MetaClassInstance) value).getId());
            } else {
                isSourceEqualsMerged = sourceValues != null && Objects.equals(sourceValues, value);
            }
        }
        return isSourceEqualsMerged ? null : value;
    }

    public List<ElementType> querySubTypes(String projectId, List<String> typeIds, Boolean isActualMatch) {
        List<MetaClassInstance> instances;
        if (Objects.equals(isActualMatch, Boolean.TRUE)) {
            instances = internalUmlService.fetchInstanceByIds(typeIds, projectId);
        } else {
            List<MetaClassInstance> stereotypeList = internalUmlService.querySpecifiedInstanceList(projectId, UMLDefinitionConstants.Stereotype);
            QueryPropertyForm queryStereotypeForm = internalUmlService.getQueryPropertyForm(stereotypeList, UMLDefinitionConstants.Stereotype_metaClass);
            MofResultContainer stereotypeContainer = internalUmlService.queryProperty(projectId, queryStereotypeForm);
            Set<String> typeIdSet = new HashSet<>(typeIds);
            Set<MetaClassInstance> extensions = stereotypeList.stream().map(it -> {
                List<MetaClassInstance> metaClassInstances = stereotypeContainer.queryListInstanceProperty(it.getId(), UMLDefinitionConstants.Stereotype_metaClass);
                if (metaClassInstances.stream().map(MetaClassInstance::getId).anyMatch(typeIdSet::contains)) {
                    return it;
                }
                return null;
            }).filter(Objects::nonNull).collect(Collectors.toSet());

            instances = internalUmlService.getSpecificsCascade(projectId, typeIds);
            instances.addAll(extensions);
        }
        Map<String, MetaClassInstance> metaClassInstanceMap = new HashMap<>();
        Map<String, MetaClassInstance> stereotypeInstanceMap = new HashMap<>();
        for (MetaClassInstance instance : instances) {
            if (iJudgeService.isMetaStereotype(projectId, instance)) {
                stereotypeInstanceMap.putIfAbsent(instance.getId(), instance);
            } else {
                metaClassInstanceMap.putIfAbsent(instance.getId(), instance);
            }
        }
        List<ElementType> result = new ArrayList<>();
        metaClassInstanceMap.values().forEach(model -> {
            ModelInfo info = managerConfig.getModelInfoConfig().get(model.getId());
            if (Objects.nonNull(info)) {
                ElementType elementType = PropertyService.makeElementType(model, info);
                result.add(elementType);
            }
        });
        List<MetaClassInstance> stereotypes = new ArrayList<>(stereotypeInstanceMap.values());
        if (CollectionUtils.isNotEmpty(stereotypes)) {
            List<ElementType> elementTypesOfStereotype = propertyService.getCustomizationElementTypes(projectId, stereotypes);
            result.addAll(elementTypesOfStereotype);
        }

        return result;

    }

    public ExpressionVerifyResultVo expressionVerify(ModelExpressionVerifyDTO modelExpressionVerifyDTO) {
        log.info("expressionVerify -> modelExpressionVerifyDTO:{}", modelExpressionVerifyDTO);
        String projectId = modelExpressionVerifyDTO.getProjectId();
        MetaClassInstance instance = internalUmlService.fetchInstance(modelExpressionVerifyDTO.getInstanceId(), projectId);
        List<MetaClassInstance> metaClassInstances = Collections.singletonList(instance);
        List<MapOperation> mapOperationList = InstanceVoUtils.transferCustomizeColumnInfoJsonToMapOperationList(modelExpressionVerifyDTO.getExpression());
        Map<String, Map<String, CustomListHolder>> allCustomListHolderMap = new HashMap<>();

        navigationService.queryCustomizeDataByOrderTraversal(projectId, metaClassInstances, mapOperationList, allCustomListHolderMap);

        ExpressionVerifyResultVo expressionVerifyResultVo = new ExpressionVerifyResultVo();
        List<ExpressionVerifyValueVo> list = new ArrayList<>();
        for (MapOperation mapOperation : mapOperationList) {
            Map<String, CustomListHolder> customListHolderMap = allCustomListHolderMap.getOrDefault(mapOperation.getId(), Collections.emptyMap());
            CustomListHolder customListHolder = customListHolderMap.get(instance.getId());
            if (customListHolder == null) {
                continue;
            }
            List<BooleanVerifyVo> booleanVerifyVos = customListHolder.getBooleanList().stream().map(e -> BooleanVerifyVo.builder().type(TypeEnum.BOOLEAN.getName()).
                    value(e).build()).collect(Collectors.toList());
            List<IntegerVerifyVo> integerVerifyVos = customListHolder.getIntegerList().stream().map(e -> IntegerVerifyVo.builder().type(TypeEnum.INTEGER.getName()).
                    value(e).build()).collect(Collectors.toList());
            List<DoubleVerifyVo> doubleVerifyVos = customListHolder.getDoubleList().stream().map(e -> DoubleVerifyVo.builder().type(TypeEnum.REAL.getName()).
                    value(e).build()).collect(Collectors.toList());
            List<StringVerifyVo> stringVerifyVos = customListHolder.getStringList().stream().map(e -> StringVerifyVo.builder().type(TypeEnum.STRING.getName()).
                    value(e).build()).collect(Collectors.toList());
            List<MetaClassInstance> metaClassInstanceList = customListHolder.getMetaClassInstanceList();
            Map<String, ExpressionVerifyModelVo> expressionVerifyModelVoMap = createExpressionVerifyModelVo(projectId, metaClassInstanceList).stream().
                    collect(Collectors.toMap(ExpressionVerifyModelVo::getInstanceId, Function.identity(), (k1, k2) -> k1));
            List<InstanceVerifyVo> instanceVerifyVos = metaClassInstanceList.stream().map(e -> InstanceVerifyVo.builder().type(TypeEnum.INSTANCE.getName()).
                    value(expressionVerifyModelVoMap.get(e.getId())).build()).collect(Collectors.toList());
            list.addAll(booleanVerifyVos);
            list.addAll(integerVerifyVos);
            list.addAll(doubleVerifyVos);
            list.addAll(stringVerifyVos);
            list.addAll(instanceVerifyVos);
        }
        expressionVerifyResultVo.setExpressionVerifyValueVos(list);

        return expressionVerifyResultVo;

    }

    private List<ExpressionVerifyModelVo> createExpressionVerifyModelVo(String projectId, List<MetaClassInstance> metaClassInstanceList) {
        if (CollectionUtils.isEmpty(metaClassInstanceList)) {
            return Collections.emptyList();
        }
        Map<String, ModelPropertyInfo> modelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, metaClassInstanceList,
                Stream.of(UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.NamedElement_qualifiedName, UMLDefinitionConstants.Element_appliedStereotype).
                        collect(Collectors.toList()));
        Map<String, String> instanceIconMap = modelPropertyInfoService.queryIconBatch(projectId, metaClassInstanceList);
        return metaClassInstanceList.stream().map(metaClassInstance -> {
            ExpressionVerifyModelVo verifyModelVo = new ExpressionVerifyModelVo();
            ModelPropertyInfo modelPropertyInfo = modelPropertyInfoMap.get(metaClassInstance.getId());
            verifyModelVo.setInstanceId(modelPropertyInfo.getInstanceId());
            verifyModelVo.setName(modelPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_name));
            verifyModelVo.setQualifiedName(modelPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_qualifiedName));
            verifyModelVo.setMetaClass(modelPropertyInfo.getInstance().getMetaClass().getId());
            List<String> appliedStereotypes = modelPropertyInfo.queryListInstanceValue(UMLDefinitionConstants.Element_appliedStereotype).stream().
                    map(MetaClassInstance::getId).collect(Collectors.toList());
            verifyModelVo.setStereotypes(appliedStereotypes);
            verifyModelVo.setIcon(instanceIconMap.get(modelPropertyInfo.getInstanceId()));
            return verifyModelVo;
        }).collect(Collectors.toList());

    }

    public List<PropertyListVo> querySelfAndRelatedPropertyList(@NotNull final String projectId,
                                                                @NotNull final String instanceId,
                                                                @NotNull final Integer displayLevel) {
        LogUtil.printOnlineLogs("projectId, instanceId, displayLevel", projectId, instanceId, displayLevel);
        final MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (instance == null) {
            return Collections.emptyList();
        }
        List<PropertyListVo> result = new ArrayList<>();
        //1 查询元模型
        String metaclass = instance.getClassifier().getId();
        //2 查询自身属性列表
        PropertyListVo selfVo = new PropertyListVo();
        selfVo.setKey("self");
        selfVo.setInstanceId(instanceId);
        final List<PropertyConfig> propertyConfig = queryPropertyListBatch(projectId, instanceId, displayLevel);
        selfVo.setProperties(propertyConfig);
        result.add(selfVo);
        //3 根据配置查询关联属性链表
        final Map<String, RelatedProperty> relatedPropertyConfig = modelManagerConfig.getRelatedPropertyConfig();
        if (relatedPropertyConfig.containsKey(metaclass)) {
            final RelatedProperty relatedProperty = relatedPropertyConfig.get(metaclass);
            for (RelatedPropertyConfig relatedConfig : relatedProperty.getConfigs()) {
                final List<MetaClassInstance> values = internalUmlService.queryListInstanceProperty(projectId,
                        instance, relatedConfig.getKey());
                if (CollectionUtils.isEmpty(values)) {
                    PropertyListVo valueVo = queryDefaultPropertyConfigs(relatedConfig);
                    result.add(valueVo);
                } else {
                    for (MetaClassInstance value : values) {
                        PropertyListVo valueVo = new PropertyListVo();
                        valueVo.setKey(relatedConfig.getKey());
                        valueVo.setInstanceId(value.getId());
                        final List<PropertyConfig> valuePropertyConfig = queryPropertyListBatch(projectId, value.getId(),
                                displayLevel);
                        //4 插入附加业务属性
                        if (CollectionUtils.isNotEmpty(relatedConfig.getExtraPropertyKeys())) {
                            List<PropertyConfig> extraConfig = queryExtraConfig(projectId, value,
                                    relatedConfig.getExtraPropertyKeys());
                            if (CollectionUtils.isNotEmpty(extraConfig)) {
                                valuePropertyConfig.addAll(0, extraConfig);
                            }
                        }
                        valueVo.setProperties(valuePropertyConfig);
                        result.add(valueVo);
                    }
                }
            }
        }

        return result;
    }

    /**
     * 属性值不存在时，返回默认列表
     *
     * @param relatedConfig
     * @return com.huawang.mdesign.model.service.vo.PropertyListVo
     * @author xz
     * @date 2025/07/10 14:04
     */
    @NotNull
    private PropertyListVo queryDefaultPropertyConfigs(RelatedPropertyConfig relatedConfig) {
        PropertyListVo valueVo = new PropertyListVo();
        final List<PropertyConfig> defaultConfigs = relatedConfig.getDefaultPropertyKeys().stream()
                .map(defaultPropertyKey -> {
                    final PropertyConfig config = managerConfig.getPropertyConfigs().get(defaultPropertyKey);
                    if (config != null) {
                        PropertyConfig newPropertyConfig = new PropertyConfig();
                        BeanUtils.copyProperties(config, newPropertyConfig);
                        newPropertyConfig.setInstanceId(null);
                        if (BooleanUtils.isFalse(newPropertyConfig.getReadonly())
                                && !RelatedPropertyConstant.WRITE_DEFAULT_PROPERTY_SET.contains(newPropertyConfig.getKey())) {
                            newPropertyConfig.setReadonly(true);
                        }
                        return newPropertyConfig;
                    }
                    return null;
                }).filter(Objects::nonNull).collect(Collectors.toList());
        valueVo.setKey(relatedConfig.getKey());
        valueVo.setInstanceId(null);
        valueVo.setProperties(defaultConfigs);
        return valueVo;
    }

    @NotNull
    private List<PropertyConfig> queryExtraConfig(@NotNull final String projectId,
                                                  @NotNull final MetaClassInstance value,
                                                  @NotNull final List<String> extraPropertyKeys) {
        return extraPropertyKeys.stream().map(extraPropertyKey -> {
            final IExtraProperty extraProperty = extraPropertyFactory.query(extraPropertyKey);
            if (extraProperty != null) {
                return extraProperty.query(projectId, value);
            } else {
                return null;
            }
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }
}
